OSVR-Core
ValueOrRange.h
Go to the documentation of this file.
1 
11 // Copyright 2015 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 #ifndef INCLUDED_ValueOrRange_h_GUID_CAAC3116_82B6_4FB9_D32D_BC3391D2D072
26 #define INCLUDED_ValueOrRange_h_GUID_CAAC3116_82B6_4FB9_D32D_BC3391D2D072
27 
28 // Internal Includes
29 // - none
30 
31 // Library/third-party includes
32 #include <boost/iterator/iterator_facade.hpp>
33 #include <boost/assert.hpp>
34 
35 // Standard includes
36 #include <algorithm>
37 #include <type_traits>
38 #include <stdexcept>
39 
40 namespace osvr {
41 
42 namespace util {
43  namespace detail {
44  template <typename ValueType>
46  : public boost::iterator_facade<
47  ValueOrRangeIterator<ValueType>, ValueType const,
48  boost::forward_traversal_tag, ValueType const> {
49  public:
50  ValueOrRangeIterator() = delete;
51  explicit ValueOrRangeIterator(ValueType initial)
52  : m_value(initial) {}
53 
54  private:
55  friend class boost::iterator_core_access;
56  void increment() { m_value++; }
57 
58  bool equal(ValueOrRangeIterator const &other) const {
59  return this->m_value == other.m_value;
60  }
61 
62  ValueType const dereference() const { return m_value; }
63  ValueType m_value;
64  };
65  } // namespace detail
66 
69  template <typename ValueType> class ValueOrRange {
70  public:
71  typedef ValueType value_type;
73  typedef const_iterator iterator;
74 
75  typedef ValueType size_type;
76 
77  static_assert(std::is_integral<ValueType>::value,
78  "Ranges only available with integral types");
79 
81  ValueOrRange() : m_begin(0), m_end(m_begin) {}
82 
84  static ValueOrRange SingleValue(ValueType val) {
85  return ValueOrRange(val);
86  }
88  static ValueOrRange RangeZeroTo(ValueType maxVal) {
89  return ValueOrRange(maxVal, 0);
90  }
91 
93  static ValueOrRange RangeMaxMin(ValueType maxVal, ValueType minVal) {
94  return ValueOrRange(maxVal, minVal);
95  }
96 
99  template <typename T> bool contains(T val) const {
100  static_assert(std::is_integral<T>::value,
101  "Ranges only available with integral types");
102  return !empty() && getMin() <= val && val <= getMax();
103  }
104 
108  ValueType getMin() const {
109  BOOST_ASSERT_MSG(!empty(), "Should only call if not empty!");
110  return m_begin;
111  }
112 
116  ValueType getMax() const {
117  BOOST_ASSERT_MSG(!empty(), "Should only call if not empty!");
118  return m_end - 1;
119  }
120 
122  bool isValue() const { return (m_begin + 1) == m_end; }
123 
125  bool isNonEmptyRange() const { return m_end > (m_begin + 1); }
126 
129  bool empty() const { return m_begin == 0 && m_end == 0; }
130 
131  size_type size() const { return m_end - m_begin; }
132 
133  value_type getValue() const {
134  BOOST_ASSERT_MSG(isValue(), "Should only call getValue if you know "
135  "it's an initialized value!");
136  return m_begin;
137  }
138 
140  void setValue(ValueType val) {
141  m_begin = val;
142  m_setMax(val);
143  }
144 
146  void setEmpty() {
147  m_begin = 0;
148  m_end = 0;
149  }
150 
159  void setRangeMaxMin(ValueType maxVal, ValueType minVal = 0) {
160  if (minVal > maxVal) {
161  setEmpty();
162  }
163  m_begin = minVal;
164  m_setMax(maxVal);
165  }
166 
169  if (other.empty()) {
170  return other;
171  }
172  if (empty()) {
173  other.setEmpty();
174  return other;
175  }
176  auto newMax = std::min(this->getMax(), other.getMax());
177  auto newMin = std::max(this->getMin(), other.getMin());
178  other.setRangeMaxMin(newMax, newMin);
179  return other;
180  }
181 
184  void extendRangeToMax(ValueType maxVal) {
185  if (empty()) {
186  throw std::logic_error(
187  "Can't extend an empty range with a new max!");
188  }
189  if (maxVal >= m_end) {
190  m_setMax(maxVal);
191  }
192  }
193 
196  const_iterator begin() const { return const_iterator(m_begin); }
197 
200  const_iterator end() const { return const_iterator(m_end); }
201 
202  private:
204  explicit ValueOrRange(ValueType val) : m_begin(val) { m_setMax(val); }
205 
207  ValueOrRange(ValueType maxVal, ValueType minVal) : m_begin(minVal) {
208  if (maxVal >= minVal) {
209  m_setMax(maxVal);
210  } else {
211  setEmpty();
212  }
213  }
214 
215  void m_setMax(ValueType maxVal) {
218  m_end = maxVal + 1;
219  }
220  ValueType m_begin;
221  ValueType m_end;
222  bool m_isInitialized;
223  };
224 } // end namespace util
225 
226 } // end namespace osvr
227 
228 #endif // INCLUDED_ValueOrRange_h_GUID_CAAC3116_82B6_4FB9_D32D_BC3391D2D072
ValueOrRange()
Default constructor: an empty range.
Definition: ValueOrRange.h:81
void extendRangeToMax(ValueType maxVal)
If this is an initialized range, extend it as needed such that the given maxVal is included...
Definition: ValueOrRange.h:184
Definition: RunLoopManager.h:42
static ValueOrRange RangeMaxMin(ValueType maxVal, ValueType minVal)
Factory method for creating a range from zero.
Definition: ValueOrRange.h:93
Class providing a unified container-like interface to either a single value or a range of integers...
Definition: ValueOrRange.h:69
bool isValue() const
Has the object been assigned a single value (range of size 1)
Definition: ValueOrRange.h:122
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
void setRangeMaxMin(ValueType maxVal, ValueType minVal=0)
Assign a range of values to this object.
Definition: ValueOrRange.h:159
bool contains(T val) const
Determine if the range contains the given value (treating a value instance of this object as essentia...
Definition: ValueOrRange.h:99
void setValue(ValueType val)
Assign a single value to this object.
Definition: ValueOrRange.h:140
detail::size< coerce_list< Ts... >> size
Get the size of a list (number of elements.)
Definition: Size.h:56
Definition: newuoa.h:1888
static ValueOrRange RangeZeroTo(ValueType maxVal)
Factory method for creating a range from zero.
Definition: ValueOrRange.h:88
const_iterator begin() const
Get a "begin" iterator pointing to the first value in the range (or value)
Definition: ValueOrRange.h:196
ValueType getMin() const
Get minimum value - closed lower bound.
Definition: ValueOrRange.h:108
bool empty() const
Is the object an empty range? (default constructor, or setting to a range with max < min) ...
Definition: ValueOrRange.h:129
static ValueOrRange SingleValue(ValueType val)
Factory method for creating a single-value range.
Definition: ValueOrRange.h:84
bool isNonEmptyRange() const
Has the object been assigned a range of size > 1?
Definition: ValueOrRange.h:125
ValueOrRange getIntersection(ValueOrRange other) const
Gets the (possibly empty) intersection of the ranges/values.
Definition: ValueOrRange.h:168
const_iterator end() const
Get a "past-the-end" iterator pointing to one more than the max value)
Definition: ValueOrRange.h:200
void setEmpty()
Assign an empty range to this object.
Definition: ValueOrRange.h:146
Definition: ValueOrRange.h:45
ValueType getMax() const
Get maximum value - closed upper bound.
Definition: ValueOrRange.h:116