1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 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 * http://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 16 #ifndef PANDA_LIBPANDABASE_UTILS_BIT_FIELD_H_ 17 #define PANDA_LIBPANDABASE_UTILS_BIT_FIELD_H_ 18 19 #include "macros.h" 20 21 namespace panda { 22 23 /* 24 * Auxiliary static class that provides access to bits range within an integer value. 25 */ 26 template <typename T, size_t start, size_t bits_num = 1> 27 class BitField { 28 static constexpr unsigned BITS_PER_BYTE = 8; 29 30 static_assert(start < sizeof(uint64_t) * BITS_PER_BYTE, "Invalid position"); 31 static_assert(bits_num != 0U, "Invalid size"); 32 static_assert(bits_num <= sizeof(uint64_t) * BITS_PER_BYTE, "Invalid size"); 33 static_assert(bits_num + start <= sizeof(uint64_t) * BITS_PER_BYTE, "Invalid position + size"); 34 35 public: 36 using ValueType = T; 37 static constexpr unsigned START_BIT = start; 38 static constexpr unsigned END_BIT = start + bits_num; 39 static constexpr unsigned SIZE = bits_num; 40 41 /* 42 * This is static class and should not be instantiated. 43 */ 44 BitField() = delete; 45 46 virtual ~BitField() = delete; 47 48 NO_COPY_SEMANTIC(BitField); 49 NO_MOVE_SEMANTIC(BitField); 50 51 /* 52 * Make BitField type follow right after current bit range. 53 * 54 * If we have 55 * BitField<T, 0, 9> 56 * then 57 * BitField<T, 0, 9>::NextField<T,3> 58 * will be equal to 59 * BitField<T, 9, 3> 60 * 61 * It is helpful when we need to specify chain of fields. 62 */ 63 template <typename T2, unsigned bits_num2> 64 using NextField = BitField<T2, start + bits_num, bits_num2>; 65 66 /* 67 * Make Flag field follow right after current bit range. 68 * Same as NextField, but no need to specify number of bits. It is always 1. 69 */ 70 using NextFlag = BitField<bool, start + bits_num, 1>; 71 72 public: 73 /* 74 * Return mask of bit range, i.e. 0b1110 for BitField<T, 1, 3> 75 */ Mask()76 static constexpr uint64_t Mask() 77 { 78 return ((1LLU << bits_num) - 1) << start; 79 } 80 81 /* 82 * Check if given value fits into the bit field 83 */ IsValid(T value)84 static constexpr bool IsValid(T value) 85 { 86 return (static_cast<uint64_t>(value) & ~((1LLU << bits_num) - 1)) == 0; 87 } 88 89 /* 90 * Set 'value' to current bit range [START_BIT : START_BIT+END_BIT] within the 'stor' parameter. 91 */ 92 template <typename Stor> Set(T value,Stor * stor)93 static constexpr void Set(T value, Stor *stor) 94 { 95 *stor = (*stor & ~Mask()) | (static_cast<uint64_t>(value) << start); 96 } 97 98 /* 99 * Return bit range [START_BIT : START_BIT+END_BIT] value from given integer 'value' 100 */ Get(uint64_t value)101 constexpr static T Get([[maybe_unused]] uint64_t value) 102 { 103 return static_cast<T>((value >> start) & ((1LLU << bits_num) - 1)); 104 } 105 106 /* 107 * Encode 'value' to current bit range [START_BIT : START_BIT+END_BIT] and return it 108 */ Encode(T value)109 static uint64_t Encode(T value) 110 { 111 ASSERT(IsValid(value)); 112 return (static_cast<uint64_t>(value) << start); 113 } 114 115 /* 116 * Update 'value' to current bit range [START_BIT : START_BIT+END_BIT] and return it 117 */ Update(uint64_t old_value,T value)118 static uint64_t Update(uint64_t old_value, T value) 119 { 120 ASSERT(IsValid(value)); 121 return (old_value & ~Mask()) | (static_cast<uint64_t>(value) << start); 122 } 123 124 /* 125 * Decode from value 126 */ Decode(uint64_t value)127 static T Decode(uint64_t value) 128 { 129 return static_cast<T>((value >> start) & ((1LLU << bits_num) - 1)); 130 } 131 }; 132 133 } // namespace panda 134 135 #endif // PANDA_LIBPANDABASE_UTILS_BIT_FIELD_H_ 136