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