// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file contains various utility routines for manipulating values at a low // level, such as byte swaps and safe casts. #ifndef EMBOSS_RUNTIME_CPP_EMBOSS_BIT_UTIL_H_ #define EMBOSS_RUNTIME_CPP_EMBOSS_BIT_UTIL_H_ #include #include #include "runtime/cpp/emboss_defines.h" namespace emboss { namespace support { // Where possible, it is best to use byte swap builtins, but if they are not // available ByteSwap can fall back to portable code. inline constexpr ::std::uint8_t ByteSwap(::std::uint8_t x) { return x; } inline constexpr ::std::uint16_t ByteSwap(::std::uint16_t x) { #ifdef EMBOSS_BYTESWAP16 return EMBOSS_BYTESWAP16(x); #else return (x << 8) | (x >> 8); #endif } inline constexpr ::std::uint32_t ByteSwap(::std::uint32_t x) { #ifdef EMBOSS_BYTESWAP32 return EMBOSS_BYTESWAP32(x); #else return (static_cast( ByteSwap(static_cast(x))) << 16) | ByteSwap(static_cast(x >> 16)); #endif } inline constexpr ::std::uint64_t ByteSwap(::std::uint64_t x) { #ifdef EMBOSS_BYTESWAP64 return EMBOSS_BYTESWAP64(x); #else return (static_cast( ByteSwap(static_cast(x))) << 32) | ByteSwap(static_cast(x >> 32)); #endif } // Masks the given value to the given number of bits. template inline constexpr T MaskToNBits(T value, unsigned bits) { static_assert(!::std::is_signed::value, "MaskToNBits only works on unsigned values."); return bits < sizeof value * 8 ? value & ((static_cast(1) << bits) - 1) : value; } template inline constexpr bool IsPowerOfTwo(T value) { // This check relies on an old bit-counting trick; x & (x - 1) always has one // fewer bit set to 1 than x (if x is nonzero), and powers of 2 always have // exactly one 1 bit, thus x & (x - 1) == 0 if x is a power of 2. return value > 0 && (value & (value - 1)) == 0; } } // namespace support } // namespace emboss #endif // EMBOSS_RUNTIME_CPP_EMBOSS_BIT_UTIL_H_