Chi-Tech
allowable_range.h
Go to the documentation of this file.
1#ifndef CHITECH_ALLOWABLE_RANGE_H
2#define CHITECH_ALLOWABLE_RANGE_H
3
4#include <string>
5#include <utility>
6#include <vector>
7#include <algorithm>
8#include <sstream>
9
11{
12
13// ##################################################################
14/**Base class for an allowable range.*/
16{
17protected:
18 virtual bool ChildIsAllowable(Varying value) const = 0;
19 virtual std::string AllowableRangeStr() const = 0;
20
21public:
22 /**Returns `true` is the value is within the allowable range.*/
23 template <typename T>
24 bool IsAllowable(const T& value)
25 {
26 return ChildIsAllowable(Varying(value));
27 }
28
29 /**Provides a formatted string of the message to display if a
30 * value is out of range.*/
31 template <typename T>
32 std::string OutOfRangeString(const std::string& scope, const T& value) const
33 {
34 const Varying vvalue(value);
35 std::stringstream outstr;
36
37 if (not scope.empty()) outstr << "Parameter \"" << scope << "\": ";
38
39 outstr << "Value " << vvalue << " out of range. ";
40 outstr << "Constraints: " << AllowableRangeStr() << ".";
41
42 return outstr.str();
43 }
44
45 /**Prints the allowable constraints to a string.*/
46 std::string PrintRange() { return AllowableRangeStr(); }
47
48 virtual ~AllowableRange() = default;
49};
50
51// ##################################################################
52/**Range comprising a list of values.*/
54{
55protected:
56 std::vector<Varying> list_;
57
58public:
59 template <typename T>
60 AllowableRangeList(const std::initializer_list<T>& raw_list)
61 {
62 for (const auto& val : raw_list)
63 list_.emplace_back(val);
64 }
65
66 template <typename T>
67 AllowableRangeList(const std::vector<T>& raw_list)
68 {
69 for (const auto& val : raw_list)
70 list_.emplace_back(val);
71 }
72
73 template <typename T>
74 static std::unique_ptr<AllowableRangeList>
75 New(const std::initializer_list<T>& raw_list)
76 {
77 return std::unique_ptr<AllowableRangeList>{
78 new AllowableRangeList(raw_list)};
79 }
80
81 template <typename T>
82 static std::unique_ptr<AllowableRangeList>
83 New(const std::vector<T>& raw_list)
84 {
85 return std::unique_ptr<AllowableRangeList>{
86 new AllowableRangeList(raw_list)};
87 }
88
89protected:
90 bool ChildIsAllowable(Varying value) const override
91 {
92 return std::find(list_.begin(), list_.end(), value) != list_.end();
93 }
94 std::string AllowableRangeStr() const override
95 {
96 std::stringstream outstr;
97 for (const auto& value : list_)
98 {
99 outstr << value;
100 if (value != list_.back()) outstr << ", ";
101 }
102 return outstr.str();
103 }
104};
105
106class AllowableRangeLowHighLimit;
107
108// ##################################################################
109/**Lower limit range.*/
111{
112protected:
114 bool low_closed_ = true;
115
116public:
117 template <typename T>
118 explicit AllowableRangeLowLimit(const T& low_value, bool low_closed = true)
119 : low_limit_(Varying(low_value)), low_closed_(low_closed)
120 {
121 }
122
123 template <typename T>
124 static std::unique_ptr<AllowableRangeLowLimit> New(const T& low_value,
125 bool low_closed = true)
126 {
127 return std::unique_ptr<AllowableRangeLowLimit>{
128 new AllowableRangeLowLimit(low_value, low_closed)};
129 }
130
131protected:
133 bool ChildIsAllowable(Varying value) const override
134 {
135 if (value.Type() != low_limit_.Type()) return false;
136
137 if (low_closed_) return value >= low_limit_;
138 else
139 return value > low_limit_;
140 }
141 std::string AllowableRangeStr() const override
142 {
143 if (low_closed_) return std::string(">= ") + low_limit_.PrintStr();
144 else
145 return std::string("> ") + low_limit_.PrintStr();
146 }
147};
148
149// ##################################################################
150/**Upper limit range.*/
152{
153protected:
155 bool hi_closed_ = true;
156
157public:
158 template <typename T>
159 explicit AllowableRangeHighLimit(const T& hi_value, bool hi_closed = true)
160 : hi_limit_(Varying(hi_value)), hi_closed_(hi_closed)
161 {
162 }
163
164 template <typename T>
165 static std::unique_ptr<AllowableRangeHighLimit> New(const T& hi_value,
166 bool hi_closed = true)
167 {
168 return std::unique_ptr<AllowableRangeHighLimit>{
169 new AllowableRangeHighLimit(hi_value, hi_closed)};
170 }
171
172protected:
174 bool ChildIsAllowable(Varying value) const override
175 {
176 if (value.Type() != hi_limit_.Type()) return false;
177
178 if (hi_closed_) return value <= hi_limit_;
179 else
180 return value < hi_limit_;
181 }
182 std::string AllowableRangeStr() const override
183 {
184 if (hi_closed_) return std::string("<= ") + hi_limit_.PrintStr();
185 else
186 return std::string("< ") + hi_limit_.PrintStr();
187 }
188};
189
190// ##################################################################
191/**Upper and lower limit range.*/
193{
194protected:
197
198public:
199 template <typename T>
200 explicit AllowableRangeLowHighLimit(const T& low_value,
201 const T& hi_value,
202 bool low_closed = true,
203 bool hi_closed = true)
204 : low_range_(Varying(low_value), low_closed),
205 hi_range(Varying(hi_value), hi_closed)
206 {
207 }
208
209 template <typename T>
210 static std::unique_ptr<AllowableRangeLowHighLimit> New(const T& low_value,
211 const T& hi_value,
212 bool low_closed = true,
213 bool hi_closed = true)
214 {
215 return std::unique_ptr<AllowableRangeLowHighLimit>{
217 low_value, hi_value, low_closed, hi_closed)};
218 }
219
220protected:
221 bool ChildIsAllowable(Varying value) const override
222 {
223 return low_range_.ChildIsAllowable(value) and
225 }
226 std::string AllowableRangeStr() const override
227 {
228
230 }
231};
232
233} // namespace chi_data_types
234
235#endif // CHITECH_ALLOWABLE_RANGE_H
AllowableRangeHighLimit(const T &hi_value, bool hi_closed=true)
std::string AllowableRangeStr() const override
static std::unique_ptr< AllowableRangeHighLimit > New(const T &hi_value, bool hi_closed=true)
bool ChildIsAllowable(Varying value) const override
virtual ~AllowableRange()=default
std::string OutOfRangeString(const std::string &scope, const T &value) const
virtual bool ChildIsAllowable(Varying value) const =0
virtual std::string AllowableRangeStr() const =0
bool IsAllowable(const T &value)
std::string AllowableRangeStr() const override
AllowableRangeList(const std::initializer_list< T > &raw_list)
AllowableRangeList(const std::vector< T > &raw_list)
static std::unique_ptr< AllowableRangeList > New(const std::vector< T > &raw_list)
bool ChildIsAllowable(Varying value) const override
static std::unique_ptr< AllowableRangeList > New(const std::initializer_list< T > &raw_list)
AllowableRangeLowHighLimit(const T &low_value, const T &hi_value, bool low_closed=true, bool hi_closed=true)
static std::unique_ptr< AllowableRangeLowHighLimit > New(const T &low_value, const T &hi_value, bool low_closed=true, bool hi_closed=true)
std::string AllowableRangeStr() const override
bool ChildIsAllowable(Varying value) const override
std::string AllowableRangeStr() const override
AllowableRangeLowLimit(const T &low_value, bool low_closed=true)
static std::unique_ptr< AllowableRangeLowLimit > New(const T &low_value, bool low_closed=true)
bool ChildIsAllowable(Varying value) const override
std::string PrintStr(bool with_type=true) const
Definition: varying.cc:285
VaryingDataType Type() const
Definition: varying.h:494