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