Bug 1507805 [wpt PR 14092] - [css-grid] Some fixes on grid-container-scrollbar-*...
[gecko.git] / mfbt / Saturate.h
blob9be327c057288da43e8c88e879f1dd4ef4c2d1e2
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* Provides saturation arithmetics for scalar types. */
9 #ifndef mozilla_Saturate_h
10 #define mozilla_Saturate_h
12 #include "mozilla/Attributes.h"
13 #include "mozilla/Move.h"
14 #include "mozilla/TypeTraits.h"
16 #include <limits>
18 namespace mozilla {
19 namespace detail {
21 /**
22 * |SaturateOp<T>| wraps scalar values for saturation arithmetics. Usage:
24 * uint32_t value = 1;
26 * ++SaturateOp<uint32_t>(value); // value is 2
27 * --SaturateOp<uint32_t>(value); // value is 1
28 * --SaturateOp<uint32_t>(value); // value is 0
29 * --SaturateOp<uint32_t>(value); // value is still 0
31 * Please add new operators when required.
33 * |SaturateOp<T>| will saturate at the minimum and maximum values of
34 * type T. If you need other bounds, implement a clamped-type class and
35 * specialize the type traits accordingly.
37 template <typename T>
38 class SaturateOp
40 public:
41 explicit SaturateOp(T& aValue)
42 : mValue(aValue)
44 // We should actually check for |std::is_scalar<T>::value| to be
45 // true, but this type trait is not available everywhere. Relax
46 // this assertion if you want to use floating point values as well.
47 static_assert(IsIntegral<T>::value,
48 "Integral type required in instantiation");
51 // Add and subtract operators
53 T operator+(const T& aRhs) const
55 return T(mValue) += aRhs;
58 T operator-(const T& aRhs) const
60 return T(mValue) -= aRhs;
63 // Compound operators
65 const T& operator+=(const T& aRhs) const
67 const T min = std::numeric_limits<T>::min();
68 const T max = std::numeric_limits<T>::max();
70 if (aRhs > static_cast<T>(0)) {
71 mValue = (max - aRhs) < mValue ? max : mValue + aRhs;
72 } else {
73 mValue = (min - aRhs) > mValue ? min : mValue + aRhs;
75 return mValue;
78 const T& operator-=(const T& aRhs) const
80 const T min = std::numeric_limits<T>::min();
81 const T max = std::numeric_limits<T>::max();
83 if (aRhs > static_cast<T>(0)) {
84 mValue = (min + aRhs) > mValue ? min : mValue - aRhs;
85 } else {
86 mValue = (max + aRhs) < mValue ? max : mValue - aRhs;
88 return mValue;
91 // Increment and decrement operators
93 const T& operator++() const // prefix
95 return operator+=(static_cast<T>(1));
98 T operator++(int) const // postfix
100 const T value(mValue);
101 operator++();
102 return value;
105 const T& operator--() const // prefix
107 return operator-=(static_cast<T>(1));
110 T operator--(int) const // postfix
112 const T value(mValue);
113 operator--();
114 return value;
117 private:
118 SaturateOp(const SaturateOp<T>&) = delete;
119 SaturateOp(SaturateOp<T>&&) = delete;
120 SaturateOp& operator=(const SaturateOp<T>&) = delete;
121 SaturateOp& operator=(SaturateOp<T>&&) = delete;
123 T& mValue;
127 * |Saturate<T>| is a value type for saturation arithmetics. It's
128 * build on top of |SaturateOp<T>|.
130 template <typename T>
131 class Saturate
133 public:
134 Saturate() = default;
135 MOZ_IMPLICIT Saturate(const Saturate<T>&) = default;
137 MOZ_IMPLICIT Saturate(Saturate<T>&& aValue)
139 mValue = std::move(aValue.mValue);
142 explicit Saturate(const T& aValue)
143 : mValue(aValue)
146 const T& value() const
148 return mValue;
151 // Compare operators
153 bool operator==(const Saturate<T>& aRhs) const
155 return mValue == aRhs.mValue;
158 bool operator!=(const Saturate<T>& aRhs) const
160 return !operator==(aRhs);
163 bool operator==(const T& aRhs) const
165 return mValue == aRhs;
168 bool operator!=(const T& aRhs) const
170 return !operator==(aRhs);
173 // Assignment operators
175 Saturate<T>& operator=(const Saturate<T>&) = default;
177 Saturate<T>& operator=(Saturate<T>&& aRhs)
179 mValue = std::move(aRhs.mValue);
180 return *this;
183 // Add and subtract operators
185 Saturate<T> operator+(const Saturate<T>& aRhs) const
187 Saturate<T> lhs(mValue);
188 return lhs += aRhs.mValue;
191 Saturate<T> operator+(const T& aRhs) const
193 Saturate<T> lhs(mValue);
194 return lhs += aRhs;
197 Saturate<T> operator-(const Saturate<T>& aRhs) const
199 Saturate<T> lhs(mValue);
200 return lhs -= aRhs.mValue;
203 Saturate<T> operator-(const T& aRhs) const
205 Saturate<T> lhs(mValue);
206 return lhs -= aRhs;
209 // Compound operators
211 Saturate<T>& operator+=(const Saturate<T>& aRhs)
213 SaturateOp<T>(mValue) += aRhs.mValue;
214 return *this;
217 Saturate<T>& operator+=(const T& aRhs)
219 SaturateOp<T>(mValue) += aRhs;
220 return *this;
223 Saturate<T>& operator-=(const Saturate<T>& aRhs)
225 SaturateOp<T>(mValue) -= aRhs.mValue;
226 return *this;
229 Saturate<T>& operator-=(const T& aRhs)
231 SaturateOp<T>(mValue) -= aRhs;
232 return *this;
235 // Increment and decrement operators
237 Saturate<T>& operator++() // prefix
239 ++SaturateOp<T>(mValue);
240 return *this;
243 Saturate<T> operator++(int) // postfix
245 return Saturate<T>(SaturateOp<T>(mValue)++);
248 Saturate<T>& operator--() // prefix
250 --SaturateOp<T>(mValue);
251 return *this;
254 Saturate<T> operator--(int) // postfix
256 return Saturate<T>(SaturateOp<T>(mValue)--);
259 private:
260 T mValue;
263 } // namespace detail
265 typedef detail::Saturate<int8_t> SaturateInt8;
266 typedef detail::Saturate<int16_t> SaturateInt16;
267 typedef detail::Saturate<int32_t> SaturateInt32;
268 typedef detail::Saturate<uint8_t> SaturateUint8;
269 typedef detail::Saturate<uint16_t> SaturateUint16;
270 typedef detail::Saturate<uint32_t> SaturateUint32;
272 } // namespace mozilla
274 template<typename LhsT, typename RhsT>
275 bool
276 operator==(LhsT aLhs, const mozilla::detail::Saturate<RhsT>& aRhs)
278 return aRhs.operator==(static_cast<RhsT>(aLhs));
281 template<typename LhsT, typename RhsT>
282 bool
283 operator!=(LhsT aLhs, const mozilla::detail::Saturate<RhsT>& aRhs)
285 return !(aLhs == aRhs);
288 #endif // mozilla_Saturate_h