/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef vm_Uint8Clamped_h #define vm_Uint8Clamped_h #include #include #include #include #include namespace js { extern uint32_t ClampDoubleToUint8(const double x); class uint8_clamped final { uint8_t val; template static constexpr uint8_t ClampIntToUint8(IntT x) { static_assert(std::is_integral_v); if constexpr (std::numeric_limits::max() < 255) { return std::clamp(x, 0, std::numeric_limits::max()); } else { return std::clamp(x, 0, 255); } } public: constexpr uint8_clamped() = default; constexpr uint8_clamped(const uint8_clamped&) = default; constexpr explicit uint8_clamped(uint8_t x) : val(x) {} constexpr explicit uint8_clamped(uint16_t x) : val(ClampIntToUint8(x)) {} constexpr explicit uint8_clamped(uint32_t x) : val(ClampIntToUint8(x)) {} constexpr explicit uint8_clamped(uint64_t x) : val(ClampIntToUint8(x)) {} constexpr explicit uint8_clamped(int8_t x) : val(ClampIntToUint8(x)) {} constexpr explicit uint8_clamped(int16_t x) : val(ClampIntToUint8(x)) {} constexpr explicit uint8_clamped(int32_t x) : val(ClampIntToUint8(x)) {} constexpr explicit uint8_clamped(int64_t x) : val(ClampIntToUint8(x)) {} explicit uint8_clamped(double x) : val(uint8_t(ClampDoubleToUint8(x))) {} constexpr uint8_clamped& operator=(const uint8_clamped&) = default; // Invoke constructors for the assignment helpers. constexpr uint8_clamped& operator=(uint8_t x) { *this = uint8_clamped{x}; return *this; } constexpr uint8_clamped& operator=(uint16_t x) { *this = uint8_clamped{x}; return *this; } constexpr uint8_clamped& operator=(uint32_t x) { *this = uint8_clamped{x}; return *this; } constexpr uint8_clamped& operator=(uint64_t x) { *this = uint8_clamped{x}; return *this; } constexpr uint8_clamped& operator=(int8_t x) { *this = uint8_clamped{x}; return *this; } constexpr uint8_clamped& operator=(int16_t x) { *this = uint8_clamped{x}; return *this; } constexpr uint8_clamped& operator=(int32_t x) { *this = uint8_clamped{x}; return *this; } constexpr uint8_clamped& operator=(int64_t x) { *this = uint8_clamped{x}; return *this; } uint8_clamped& operator=(const double x) { *this = uint8_clamped{x}; return *this; } constexpr operator uint8_t() const { return val; } }; static_assert(sizeof(uint8_clamped) == 1, "uint8_clamped must be layout-compatible with uint8_t"); static_assert(std::is_trivial_v, "uint8_clamped must be trivial to be eligible for memcpy/memset " "optimizations"); } // namespace js template <> class std::numeric_limits { public: static constexpr bool is_specialized = true; static constexpr bool is_signed = false; static constexpr bool is_integer = true; static constexpr bool is_exact = true; static constexpr bool has_infinity = false; static constexpr bool has_quiet_NaN = false; static constexpr bool has_signaling_NaN = false; static constexpr std::float_denorm_style has_denorm = std::denorm_absent; static constexpr bool has_denorm_loss = false; static constexpr std::float_round_style round_style = std::round_toward_zero; static constexpr bool is_iec559 = false; static constexpr bool is_bounded = true; static constexpr bool is_modulo = false; static constexpr int digits = CHAR_BIT; static constexpr int digits10 = int(digits * /* std::log10(2) */ 0.30102999); static constexpr int max_digits10 = 0; static constexpr int radix = 2; static constexpr int min_exponent = 0; static constexpr int min_exponent10 = 0; static constexpr int max_exponent = 0; static constexpr int max_exponent10 = 0; static constexpr bool traps = true; static constexpr bool tinyness_before = false; static constexpr auto min() noexcept { return js::uint8_clamped{0}; } static constexpr auto lowest() noexcept { return min(); } static constexpr auto max() noexcept { return js::uint8_clamped{255}; } static constexpr auto epsilon() noexcept { return js::uint8_clamped{0}; } static constexpr auto round_error() noexcept { return js::uint8_clamped{0}; } static constexpr auto infinity() noexcept { return js::uint8_clamped{0}; } static constexpr auto quiet_NaN() noexcept { return js::uint8_clamped{0}; } static constexpr auto signaling_NaN() noexcept { return js::uint8_clamped{0}; } static constexpr auto denorm_min() noexcept { return js::uint8_clamped{0}; } }; #endif // vm_Uint8Clamped_h