/* vim:set ts=2 sw=2 sts=2 et: */ /** * \author Marcus Holland-Moritz (github@mhxnet.de) * \copyright Copyright (c) Marcus Holland-Moritz * * This file is part of ricepp. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the “Software”), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include "ricepp_cpuspecific.h" namespace ricepp::detail { template class dynamic_pixel_traits { public: using value_type = ValueType; static constexpr size_t const kBitCount = std::numeric_limits::digits; static constexpr value_type const kAllOnes = std::numeric_limits::max(); dynamic_pixel_traits(std::endian byteorder, unsigned unused_lsb_count) noexcept : unused_lsb_count_{unused_lsb_count} , byteorder_{byteorder} #ifndef NDEBUG , lsb_mask_{static_cast(~(kAllOnes << unused_lsb_count))} , msb_mask_{static_cast(~(kAllOnes >> unused_lsb_count))} #endif { assert(unused_lsb_count < kBitCount); } [[nodiscard]] RICEPP_FORCE_INLINE value_type read(value_type value) const noexcept { value_type tmp = ricepp::byteswap(value, byteorder_); assert((tmp & lsb_mask_) == 0); return tmp >> unused_lsb_count_; } [[nodiscard]] RICEPP_FORCE_INLINE value_type write(value_type value) const noexcept { assert((value & msb_mask_) == 0); return ricepp::byteswap(static_cast(value << unused_lsb_count_), byteorder_); } private: unsigned const unused_lsb_count_; std::endian const byteorder_; #ifndef NDEBUG value_type const lsb_mask_; value_type const msb_mask_; #endif }; template class static_pixel_traits { public: using value_type = ValueType; static constexpr size_t const kBitCount = std::numeric_limits::digits; static constexpr value_type const kAllOnes = std::numeric_limits::max(); static constexpr std::endian const kByteOrder = ByteOrder; static constexpr unsigned const kUnusedLsbCount = UnusedLsbCount; static constexpr value_type const kLsbMask = static_cast(~(kAllOnes << kUnusedLsbCount)); static constexpr value_type const kMsbMask = static_cast(~(kAllOnes >> kUnusedLsbCount)); static_assert(kUnusedLsbCount < kBitCount); [[nodiscard]] static RICEPP_FORCE_INLINE value_type read(value_type value) noexcept { value_type tmp = ricepp::byteswap(value); assert((tmp & kLsbMask) == 0); return tmp >> kUnusedLsbCount; } [[nodiscard]] static RICEPP_FORCE_INLINE value_type write(value_type value) noexcept { assert((value & kMsbMask) == 0); return ricepp::byteswap( static_cast(value << kUnusedLsbCount)); } }; template