1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // This file contains various utility routines for manipulating values at a low
16 // level, such as byte swaps and safe casts.
17 #ifndef EMBOSS_RUNTIME_CPP_EMBOSS_BIT_UTIL_H_
18 #define EMBOSS_RUNTIME_CPP_EMBOSS_BIT_UTIL_H_
19
20 #include <cstdint>
21 #include <type_traits>
22
23 #include "runtime/cpp/emboss_defines.h"
24
25 namespace emboss {
26 namespace support {
27
28 // Where possible, it is best to use byte swap builtins, but if they are not
29 // available ByteSwap can fall back to portable code.
ByteSwap(::std::uint8_t x)30 inline constexpr ::std::uint8_t ByteSwap(::std::uint8_t x) { return x; }
ByteSwap(::std::uint16_t x)31 inline constexpr ::std::uint16_t ByteSwap(::std::uint16_t x) {
32 #ifdef EMBOSS_BYTESWAP16
33 return EMBOSS_BYTESWAP16(x);
34 #else
35 return (x << 8) | (x >> 8);
36 #endif
37 }
ByteSwap(::std::uint32_t x)38 inline constexpr ::std::uint32_t ByteSwap(::std::uint32_t x) {
39 #ifdef EMBOSS_BYTESWAP32
40 return EMBOSS_BYTESWAP32(x);
41 #else
42 return (static_cast</**/ ::std::uint32_t>(
43 ByteSwap(static_cast</**/ ::std::uint16_t>(x)))
44 << 16) |
45 ByteSwap(static_cast</**/ ::std::uint16_t>(x >> 16));
46 #endif
47 }
ByteSwap(::std::uint64_t x)48 inline constexpr ::std::uint64_t ByteSwap(::std::uint64_t x) {
49 #ifdef EMBOSS_BYTESWAP64
50 return EMBOSS_BYTESWAP64(x);
51 #else
52 return (static_cast</**/ ::std::uint64_t>(
53 ByteSwap(static_cast</**/ ::std::uint32_t>(x)))
54 << 32) |
55 ByteSwap(static_cast</**/ ::std::uint32_t>(x >> 32));
56 #endif
57 }
58
59 // Masks the given value to the given number of bits.
60 template <typename T>
MaskToNBits(T value,unsigned bits)61 inline constexpr T MaskToNBits(T value, unsigned bits) {
62 static_assert(!::std::is_signed<T>::value,
63 "MaskToNBits only works on unsigned values.");
64 return bits < sizeof value * 8 ? value & ((static_cast<T>(1) << bits) - 1)
65 : value;
66 }
67
68 template <typename T>
IsPowerOfTwo(T value)69 inline constexpr bool IsPowerOfTwo(T value) {
70 // This check relies on an old bit-counting trick; x & (x - 1) always has one
71 // fewer bit set to 1 than x (if x is nonzero), and powers of 2 always have
72 // exactly one 1 bit, thus x & (x - 1) == 0 if x is a power of 2.
73 return value > 0 && (value & (value - 1)) == 0;
74 }
75
76 } // namespace support
77 } // namespace emboss
78
79 #endif // EMBOSS_RUNTIME_CPP_EMBOSS_BIT_UTIL_H_
80