001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.lang3;
019
020/**
021 * Supports operations on bit-mapped fields. Instances of this class can be used to store a flag or data within an {@code int}, {@code short} or {@code byte}.
022 * <p>
023 * Each {@link BitField} is constructed with a mask value, which indicates the bits that will be used to store and retrieve the data for that field. For
024 * instance, the mask {@code 0xFF} indicates the least-significant byte should be used to store the data.
025 * </p>
026 * <p>
027 * As an example, consider a car painting machine that accepts paint instructions as integers. Bit fields can be used to encode this:
028 * </p>
029 *
030 * <pre>
031 *
032 * // blue, green and red are 1 byte values (0-255) stored in the three least
033 * // significant bytes
034 * BitField blue = new BitField(0xFF);
035 *
036 * BitField green = new BitField(0xFF00);
037 *
038 * BitField red = new BitField(0xFF0000);
039 *
040 * // anyColor is a flag triggered if any color is used
041 * BitField anyColor = new BitField(0xFFFFFF);
042 *
043 * // isMetallic is a single bit flag
044 * BitField isMetallic = new BitField(0x1000000);
045 * </pre>
046 * <p>
047 * Using these {@link BitField} instances, a paint instruction can be encoded into an integer:
048 * </p>
049 *
050 * <pre>
051 * int paintInstruction = 0;
052 * paintInstruction = red.setValue(paintInstruction, 35);
053 * paintInstruction = green.setValue(paintInstruction, 100);
054 * paintInstruction = blue.setValue(paintInstruction, 255);
055 * </pre>
056 * <p>
057 * Flags and data can be retrieved from the integer:
058 * </p>
059 *
060 * <pre>
061 * // Prints true if red, green or blue is non-zero
062 * System.out.println(anyColor.isSet(paintInstruction)); // prints true
063 * // Prints value of red, green and blue
064 * System.out.println(red.getValue(paintInstruction)); // prints 35
065 * System.out.println(green.getValue(paintInstruction)); // prints 100
066 * System.out.println(blue.getValue(paintInstruction)); // prints 255
067 * // Prints true if isMetallic was set
068 * System.out.println(isMetallic.isSet(paintInstruction)); // prints false
069 * </pre>
070 *
071 * @since 2.0
072 */
073public class BitField {
074
075    private final long mask;
076
077    private final int shiftCount;
078
079    /**
080     * Creates a BitField instance.
081     *
082     * @param mask The mask specifying which bits apply to this BitField. Bits that are set in this mask are the bits that this BitField operates on.
083     */
084    public BitField(final int mask) {
085        this.mask = Integer.toUnsignedLong(mask);
086        this.shiftCount = this.mask == 0 ? 0 : Long.numberOfTrailingZeros(this.mask);
087    }
088
089    /**
090     * Creates a BitField instance.
091     * <p>
092     * If any bit above bit 31 is set in the mask, the resulting field can only be used with the {@code long} holder accessors; the {@code int}, {@code short}
093     * and {@code byte} holder accessors throw {@link IllegalStateException} for such a field, because those holder types cannot contain the masked bits and
094     * would otherwise silently answer wrongly (shift counts are truncated mod 32 and negative holders are sign-extended into bits 32-63).
095     * </p>
096     *
097     * @param mask The mask specifying which bits apply to this BitField. Bits that are set in this mask are the bits that this BitField operates on.
098     * @since 3.21.0
099     */
100    public BitField(final long mask) {
101        this.mask = mask;
102        this.shiftCount = mask == 0 ? 0 : Long.numberOfTrailingZeros(mask);
103    }
104
105    /**
106     * Clears the bits.
107     *
108     * @param holder The int data containing the bits we're interested in.
109     * @return The value of holder with the specified bits cleared (set to {@code 0}).
110     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
111     *         represented in this holder type.
112     */
113    public int clear(final int holder) {
114        return (int) (holder & ~intMask());
115    }
116
117    /**
118     * Clears the bits.
119     *
120     * @param holder The long data containing the bits we're interested in.
121     * @return The value of holder with the specified bits cleared (set to {@code 0}).
122     * @since 3.21.0
123     */
124    public long clear(final long holder) {
125        return holder & ~mask;
126    }
127
128    /**
129     * Clears the bits.
130     *
131     * @param holder The byte data containing the bits we're interested in.
132     * @return The value of holder with the specified bits cleared (set to {@code 0}).
133     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
134     *         represented in this holder type.
135     */
136    public byte clearByte(final byte holder) {
137        return (byte) clear(holder);
138    }
139
140    /**
141     * Clears the bits.
142     *
143     * @param holder The short data containing the bits we're interested in.
144     * @return The value of holder with the specified bits cleared (set to {@code 0}).
145     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
146     *         represented in this holder type.
147     */
148    public short clearShort(final short holder) {
149        return (short) clear(holder);
150    }
151
152    /**
153     * Gets the value for the specified BitField, unshifted.
154     *
155     * @param holder The int data containing the bits we're interested in.
156     * @return The selected bits.
157     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
158     *         represented in this holder type.
159     */
160    public int getRawValue(final int holder) {
161        return (int) (holder & intMask());
162    }
163
164    /**
165     * Gets the value for the specified BitField, unshifted.
166     *
167     * @param holder The long data containing the bits we're interested in.
168     * @return The selected bits.
169     * @since 3.21.0
170     */
171    public long getRawValue(final long holder) {
172        return holder & mask;
173    }
174
175    /**
176     * Gets the value for the specified BitField, unshifted.
177     *
178     * @param holder The short data containing the bits we're interested in.
179     * @return The selected bits.
180     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
181     *         represented in this holder type.
182     */
183    public short getShortRawValue(final short holder) {
184        return (short) getRawValue(holder);
185    }
186
187    /**
188     * Gets the value for the specified BitField, appropriately shifted right, as a short.
189     * <p>
190     * Many users of a BitField will want to treat the specified bits as an int value, and will not want to be aware that the value is stored as a BitField (and
191     * so shifted left so many bits).
192     * </p>
193     *
194     * @param holder The short data containing the bits we're interested in.
195     * @return The selected bits, shifted right appropriately.
196     * @see #setShortValue(short,short)
197     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
198     *         represented in this holder type.
199     */
200    public short getShortValue(final short holder) {
201        return (short) getValue(holder);
202    }
203
204    /**
205     * Gets the value for the specified BitField, appropriately shifted right.
206     * <p>
207     * Many users of a BitField will want to treat the specified bits as an int value, and will not want to be aware that the value is stored as a BitField (and
208     * so shifted left so many bits).
209     * </p>
210     *
211     * @param holder The int data containing the bits we're interested in.
212     * @return The selected bits, shifted right appropriately.
213     * @see #setValue(int,int)
214     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
215     *         represented in this holder type.
216     */
217    public int getValue(final int holder) {
218        return getRawValue(holder) >>> shiftCount;
219    }
220
221    /**
222     * Gets the value for the specified BitField, appropriately shifted right.
223     * <p>
224     * Many users of a BitField will want to treat the specified bits as an long value, and will not want to be aware that the value is stored as a BitField (and
225     * so shifted left so many bits).
226     * </p>
227     *
228     * @param holder The long data containing the bits we're interested in.
229     * @return The selected bits, shifted right appropriately.
230     * @see #setValue(long,long)
231     * @since 3.21.0
232     */
233    public long getValue(final long holder) {
234        return getRawValue(holder) >>> shiftCount;
235    }
236
237    /**
238     * Verifies that this field's mask fits in an {@code int} holder before an {@code int}, {@code short} or {@code byte} accessor uses it.
239     * <p>
240     * Without this check, a mask with bits above bit 31 makes the narrow accessors silently wrong: the {@code int} shift count is truncated mod 32, and a
241     * negative narrow holder is sign-extended to 64 bits before the {@code long} mask is applied, reporting above-bit-31 flags as set even though the holder
242     * type cannot contain them.
243     * </p>
244     *
245     * @return the mask, guaranteed to fit in 32 bits.
246     * @throws IllegalStateException Thrown if the mask has bits set above bit 31.
247     */
248    private long intMask() {
249        if (mask >>> Integer.SIZE != 0) {
250            throw new IllegalStateException("BitField mask 0x" + Long.toHexString(mask) + " exceeds 32 bits; use the long accessors for this field.");
251        }
252        return mask;
253    }
254
255    /**
256     * Tests whether all of the bits are set or not.
257     * <p>
258     * This is a stricter test than {@link #isSet(int)}, in that all of the bits in a multi-bit set must be set for this method to return {@code true}.
259     * </p>
260     *
261     * @param holder The int data containing the bits we're interested in.
262     * @return {@code true} if all of the bits are set, else {@code false}.
263     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
264     *         represented in this holder type.
265     */
266    public boolean isAllSet(final int holder) {
267        final long intMask = intMask();
268        return (holder & intMask) == intMask;
269    }
270
271    /**
272     * Tests whether all of the bits are set or not.
273     * <p>
274     * This is a stricter test than {@link #isSet(long)}, in that all of the bits in a multi-bit set must be set for this method to return {@code true}.
275     * </p>
276     *
277     * @param holder The long data containing the bits we're interested in.
278     * @return {@code true} if all of the bits are set, else {@code false}.
279     * @since 3.21.0
280     */
281    public boolean isAllSet(final long holder) {
282        return (holder & mask) == mask;
283    }
284
285    /**
286     * Tests whether the field is set or not.
287     * <p>
288     * This is most commonly used for a single-bit field, which is often used to represent a boolean value; the results of using it for a multi-bit field is to
289     * determine whether <em>any</em> of its bits are set.
290     * </p>
291     *
292     * @param holder The int data containing the bits we're interested in
293     * @return {@code true} if any of the bits are set, else {@code false}
294     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
295     *         represented in this holder type.
296     */
297    public boolean isSet(final int holder) {
298        return (holder & intMask()) != 0;
299    }
300
301    /**
302     * Tests whether the field is set or not.
303     * <p>
304     * This is most commonly used for a single-bit field, which is often used to represent a boolean value; the results of using it for a multi-bit field is to
305     * determine whether <em>any</em> of its bits are set.
306     * </p>
307     *
308     * @param holder The long data containing the bits we're interested in
309     * @return {@code true} if any of the bits are set, else {@code false}
310     * @since 3.21.0
311     */
312    public boolean isSet(final long holder) {
313        return (holder & mask) != 0;
314    }
315
316    /**
317     * Sets the bits.
318     *
319     * @param holder The int data containing the bits we're interested in.
320     * @return The value of holder with the specified bits set to {@code 1}.
321     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
322     *         represented in this holder type.
323     */
324    public int set(final int holder) {
325        return (int) (holder | intMask());
326    }
327
328    /**
329     * Sets the bits.
330     *
331     * @param holder The long data containing the bits we're interested in.
332     * @return The value of holder with the specified bits set to {@code 1}.
333     * @since 3.21.0
334     */
335    public long set(final long holder) {
336        return holder | mask;
337    }
338
339    /**
340     * Sets a boolean BitField.
341     *
342     * @param holder The int data containing the bits we're interested in.
343     * @param flag   indicating whether to set or clear the bits.
344     * @return The value of holder with the specified bits set or cleared.
345     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
346     *         represented in this holder type.
347     */
348    public int setBoolean(final int holder, final boolean flag) {
349        return flag ? set(holder) : clear(holder);
350    }
351
352    /**
353     * Sets a boolean BitField.
354     *
355     * @param holder The long data containing the bits we're interested in.
356     * @param flag   indicating whether to set or clear the bits.
357     * @return The value of holder with the specified bits set or cleared.
358     * @since 3.21.0
359     */
360    public long setBoolean(final long holder, final boolean flag) {
361        return flag ? set(holder) : clear(holder);
362    }
363
364    /**
365     * Sets the bits.
366     *
367     * @param holder The byte data containing the bits we're interested in
368     * @return The value of holder with the specified bits set to {@code 1}
369     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
370     *         represented in this holder type.
371     */
372    public byte setByte(final byte holder) {
373        return (byte) set(holder);
374    }
375
376    /**
377     * Sets a boolean BitField.
378     *
379     * @param holder The byte data containing the bits we're interested in.
380     * @param flag   indicating whether to set or clear the bits.
381     * @return The value of holder with the specified bits set or cleared.
382     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
383     *         represented in this holder type.
384     */
385    public byte setByteBoolean(final byte holder, final boolean flag) {
386        return flag ? setByte(holder) : clearByte(holder);
387    }
388
389    /**
390     * Sets the bits.
391     *
392     * @param holder The short data containing the bits we're interested in.
393     * @return The value of holder with the specified bits set to {@code 1}.
394     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
395     *         represented in this holder type.
396     */
397    public short setShort(final short holder) {
398        return (short) set(holder);
399    }
400
401    /**
402     * Sets a boolean BitField.
403     *
404     * @param holder The short data containing the bits we're interested in.
405     * @param flag   indicating whether to set or clear the bits.
406     * @return The value of holder with the specified bits set or cleared.
407     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
408     *         represented in this holder type.
409     */
410    public short setShortBoolean(final short holder, final boolean flag) {
411        return flag ? setShort(holder) : clearShort(holder);
412    }
413
414    /**
415     * Sets the bits with new values.
416     *
417     * @param holder The short data containing the bits we're interested in
418     * @param value  The new value for the specified bits
419     * @return The value of holder with the bits from the value parameter replacing the old bits
420     * @see #getShortValue(short)
421     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
422     *         represented in this holder type.
423     */
424    public short setShortValue(final short holder, final short value) {
425        return (short) setValue(holder, value);
426    }
427
428    /**
429     * Sets the bits with new values.
430     *
431     * @param holder The int data containing the bits we're interested in.
432     * @param value  The new value for the specified bits.
433     * @return The value of holder with the bits from the value parameter replacing the old bits.
434     * @see #getValue(int)
435     * @throws IllegalStateException Thrown if this field's mask has bits set above bit 31 (only possible via {@link #BitField(long)}) and so cannot be
436     *         represented in this holder type.
437     */
438    public int setValue(final int holder, final int value) {
439        final long intMask = intMask();
440        return (int) (holder & ~intMask | value << shiftCount & intMask);
441    }
442
443    /**
444     * Sets the bits with new values.
445     *
446     * @param holder The long data containing the bits we're interested in.
447     * @param value  The new value for the specified bits.
448     * @return The value of holder with the bits from the value parameter replacing the old bits.
449     * @see #getValue(long)
450     * @since 3.21.0
451     */
452    public long setValue(final long holder, final long value) {
453        return holder & ~mask | value << shiftCount & mask;
454    }
455}