xref: /aosp_15_r20/external/icing/icing/util/bit-util.h (revision 8b6cd535a057e39b3b86660c4aa06c99747c2136)
1 // Copyright (C) 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 //      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 #ifndef ICING_UTIL_BIT_UTIL_H_
16 #define ICING_UTIL_BIT_UTIL_H_
17 
18 #include <cstdint>
19 
20 namespace icing {
21 namespace lib {
22 
23 namespace bit_util {
24 
25 // Manipulating bit fields.
26 //
27 // value       value containing the bit field(s)
28 // lsb_offset  offset of bit field in value, starting from the least significant
29 //             bit. for example, the '1' in '0100' has a lsb_offset of 2
30 // len         len of bit field in value
31 //
32 // REQUIREMENTS
33 //
34 // - value is an unsigned integer <= 64 bits
35 // - lsb_offset + len <= sizeof(value) * 8
36 //
37 // There is no error checking so you will get garbage if you don't
38 // ensure the above.
39 
40 // Shifting by more than the word length is undefined (on ARM it has the
41 // intended effect, but on Intel it shifts by % word length), so check the
42 // length).
BitfieldMask(uint32_t len)43 inline uint64_t BitfieldMask(uint32_t len) {
44   return ((len == 0) ? 0U : ((~uint64_t{0}) >> (64 - (len))));
45 }
46 
BitfieldClear(uint32_t lsb_offset,uint32_t len,uint8_t * value_out)47 inline void BitfieldClear(uint32_t lsb_offset, uint32_t len,
48                           uint8_t* value_out) {
49   *value_out &= ~(BitfieldMask(len) << lsb_offset);
50 }
51 
BitfieldClear(uint32_t lsb_offset,uint32_t len,uint16_t * value_out)52 inline void BitfieldClear(uint32_t lsb_offset, uint32_t len,
53                           uint16_t* value_out) {
54   *value_out &= ~(BitfieldMask(len) << lsb_offset);
55 }
56 
BitfieldClear(uint32_t lsb_offset,uint32_t len,uint32_t * value_out)57 inline void BitfieldClear(uint32_t lsb_offset, uint32_t len,
58                           uint32_t* value_out) {
59   *value_out &= ~(BitfieldMask(len) << lsb_offset);
60 }
61 
BitfieldClear(uint32_t lsb_offset,uint32_t len,uint64_t * value_out)62 inline void BitfieldClear(uint32_t lsb_offset, uint32_t len,
63                           uint64_t* value_out) {
64   *value_out &= ~(BitfieldMask(len) << lsb_offset);
65 }
66 
BitfieldGet(uint64_t value,uint32_t lsb_offset,uint32_t len)67 inline uint64_t BitfieldGet(uint64_t value, uint32_t lsb_offset, uint32_t len) {
68   return ((value) >> (lsb_offset)) & BitfieldMask(len);
69 }
70 
BitfieldSet(uint8_t new_value,uint32_t lsb_offset,uint32_t len,uint8_t * value_out)71 inline void BitfieldSet(uint8_t new_value, uint32_t lsb_offset, uint32_t len,
72                         uint8_t* value_out) {
73   BitfieldClear(lsb_offset, len, value_out);
74 
75   // We conservatively mask new_value at len so value won't be corrupted if
76   // new_value >= (1 << len).
77   *value_out |= (new_value & BitfieldMask(len)) << (lsb_offset);
78 }
79 
BitfieldSet(uint16_t new_value,uint32_t lsb_offset,uint32_t len,uint16_t * value_out)80 inline void BitfieldSet(uint16_t new_value, uint32_t lsb_offset, uint32_t len,
81                         uint16_t* value_out) {
82   BitfieldClear(lsb_offset, len, value_out);
83 
84   // We conservatively mask new_value at len so value won't be corrupted if
85   // new_value >= (1 << len).
86   *value_out |= (new_value & BitfieldMask(len)) << (lsb_offset);
87 }
88 
BitfieldSet(uint32_t new_value,uint32_t lsb_offset,uint32_t len,uint32_t * value_out)89 inline void BitfieldSet(uint32_t new_value, uint32_t lsb_offset, uint32_t len,
90                         uint32_t* value_out) {
91   BitfieldClear(lsb_offset, len, value_out);
92 
93   // We conservatively mask new_value at len so value won't be corrupted if
94   // new_value >= (1 << len).
95   *value_out |= (new_value & BitfieldMask(len)) << (lsb_offset);
96 }
97 
BitfieldSet(uint64_t new_value,uint32_t lsb_offset,uint32_t len,uint64_t * value_out)98 inline void BitfieldSet(uint64_t new_value, uint32_t lsb_offset, uint32_t len,
99                         uint64_t* value_out) {
100   BitfieldClear(lsb_offset, len, value_out);
101 
102   // We conservatively mask new_value at len so value won't be corrupted if
103   // new_value >= (1 << len).
104   *value_out |= (new_value & BitfieldMask(len)) << (lsb_offset);
105 }
106 
107 }  // namespace bit_util
108 
109 }  // namespace lib
110 }  // namespace icing
111 
112 #endif  // ICING_UTIL_BIT_UTIL_H_
113