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 *      http://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 */
017package org.apache.commons.lang3;
018
019/**
020 * <p>Operations on bit-mapped fields.</p>
021 *
022 * @since 2.0
023 * @version $Id: BitField.java 1436768 2013-01-22 07:07:42Z ggregory $
024 */
025public class BitField {
026    
027    private final int _mask;
028    private final int _shift_count;
029
030    /**
031     * <p>Creates a BitField instance.</p>
032     *
033     * @param mask the mask specifying which bits apply to this
034     *  BitField. Bits that are set in this mask are the bits
035     *  that this BitField operates on
036     */
037    public BitField(final int mask) {
038        _mask = mask;
039        int count = 0;
040        int bit_pattern = mask;
041
042        if (bit_pattern != 0) {
043            while ((bit_pattern & 1) == 0) {
044                count++;
045                bit_pattern >>= 1;
046            }
047        }
048        _shift_count = count;
049    }
050
051    /**
052     * <p>Obtains the value for the specified BitField, appropriately
053     * shifted right.</p>
054     *
055     * <p>Many users of a BitField will want to treat the specified
056     * bits as an int value, and will not want to be aware that the
057     * value is stored as a BitField (and so shifted left so many
058     * bits).</p>
059     *
060     * @see #setValue(int,int)
061     * @param holder the int data containing the bits we're interested
062     *  in
063     * @return the selected bits, shifted right appropriately
064     */
065    public int getValue(final int holder) {
066        return getRawValue(holder) >> _shift_count;
067    }
068
069    /**
070     * <p>Obtains the value for the specified BitField, appropriately
071     * shifted right, as a short.</p>
072     *
073     * <p>Many users of a BitField will want to treat the specified
074     * bits as an int value, and will not want to be aware that the
075     * value is stored as a BitField (and so shifted left so many
076     * bits).</p>
077     *
078     * @see #setShortValue(short,short)
079     * @param holder the short data containing the bits we're
080     *  interested in
081     * @return the selected bits, shifted right appropriately
082     */
083    public short getShortValue(final short holder) {
084        return (short) getValue(holder);
085    }
086
087    /**
088     * <p>Obtains the value for the specified BitField, unshifted.</p>
089     *
090     * @param holder the int data containing the bits we're
091     *  interested in
092     * @return the selected bits
093     */
094    public int getRawValue(final int holder) {
095        return holder & _mask;
096    }
097
098    /**
099     * <p>Obtains the value for the specified BitField, unshifted.</p>
100     *
101     * @param holder the short data containing the bits we're
102     *  interested in
103     * @return the selected bits
104     */
105    public short getShortRawValue(final short holder) {
106        return (short) getRawValue(holder);
107    }
108
109    /**
110     * <p>Returns whether the field is set or not.</p>
111     *
112     * <p>This is most commonly used for a single-bit field, which is
113     * often used to represent a boolean value; the results of using
114     * it for a multi-bit field is to determine whether *any* of its
115     * bits are set.</p>
116     *
117     * @param holder the int data containing the bits we're interested
118     *  in
119     * @return {@code true} if any of the bits are set,
120     *  else {@code false}
121     */
122    public boolean isSet(final int holder) {
123        return (holder & _mask) != 0;
124    }
125
126    /**
127     * <p>Returns whether all of the bits are set or not.</p>
128     *
129     * <p>This is a stricter test than {@link #isSet(int)},
130     * in that all of the bits in a multi-bit set must be set
131     * for this method to return {@code true}.</p>
132     *
133     * @param holder the int data containing the bits we're
134     *  interested in
135     * @return {@code true} if all of the bits are set,
136     *  else {@code false}
137     */
138    public boolean isAllSet(final int holder) {
139        return (holder & _mask) == _mask;
140    }
141
142    /**
143     * <p>Replaces the bits with new values.</p>
144     *
145     * @see #getValue(int)
146     * @param holder the int data containing the bits we're
147     *  interested in
148     * @param value the new value for the specified bits
149     * @return the value of holder with the bits from the value
150     *  parameter replacing the old bits
151     */
152    public int setValue(final int holder, final int value) {
153        return (holder & ~_mask) | ((value << _shift_count) & _mask);
154    }
155
156    /**
157     * <p>Replaces the bits with new values.</p>
158     *
159     * @see #getShortValue(short)
160     * @param holder the short data containing the bits we're
161     *  interested in
162     * @param value the new value for the specified bits
163     * @return the value of holder with the bits from the value
164     *  parameter replacing the old bits
165     */
166    public short setShortValue(final short holder, final short value) {
167        return (short) setValue(holder, value);
168    }
169
170    /**
171     * <p>Clears the bits.</p>
172     *
173     * @param holder the int data containing the bits we're
174     *  interested in
175     * @return the value of holder with the specified bits cleared
176     *  (set to {@code 0})
177     */
178    public int clear(final int holder) {
179        return holder & ~_mask;
180    }
181
182    /**
183     * <p>Clears the bits.</p>
184     *
185     * @param holder the short data containing the bits we're
186     *  interested in
187     * @return the value of holder with the specified bits cleared
188     *  (set to {@code 0})
189     */
190    public short clearShort(final short holder) {
191        return (short) clear(holder);
192    }
193
194    /**
195     * <p>Clears the bits.</p>
196     *
197     * @param holder the byte data containing the bits we're
198     *  interested in
199     *
200     * @return the value of holder with the specified bits cleared
201     *  (set to {@code 0})
202     */
203    public byte clearByte(final byte holder) {
204        return (byte) clear(holder);
205    }
206
207    /**
208     * <p>Sets the bits.</p>
209     *
210     * @param holder the int data containing the bits we're
211     *  interested in
212     * @return the value of holder with the specified bits set
213     *  to {@code 1}
214     */
215    public int set(final int holder) {
216        return holder | _mask;
217    }
218
219    /**
220     * <p>Sets the bits.</p>
221     *
222     * @param holder the short data containing the bits we're
223     *  interested in
224     * @return the value of holder with the specified bits set
225     *  to {@code 1}
226     */
227    public short setShort(final short holder) {
228        return (short) set(holder);
229    }
230
231    /**
232     * <p>Sets the bits.</p>
233     *
234     * @param holder the byte data containing the bits we're
235     *  interested in
236     *
237     * @return the value of holder with the specified bits set
238     *  to {@code 1}
239     */
240    public byte setByte(final byte holder) {
241        return (byte) set(holder);
242    }
243
244    /**
245     * <p>Sets a boolean BitField.</p>
246     *
247     * @param holder the int data containing the bits we're
248     *  interested in
249     * @param flag indicating whether to set or clear the bits
250     * @return the value of holder with the specified bits set or
251     *         cleared
252     */
253    public int setBoolean(final int holder, final boolean flag) {
254        return flag ? set(holder) : clear(holder);
255    }
256
257    /**
258     * <p>Sets a boolean BitField.</p>
259     *
260     * @param holder the short data containing the bits we're
261     *  interested in
262     * @param flag indicating whether to set or clear the bits
263     * @return the value of holder with the specified bits set or
264     *  cleared
265     */
266    public short setShortBoolean(final short holder, final boolean flag) {
267        return flag ? setShort(holder) : clearShort(holder);
268    }
269
270    /**
271     * <p>Sets a boolean BitField.</p>
272     *
273     * @param holder the byte data containing the bits we're
274     *  interested in
275     * @param flag indicating whether to set or clear the bits
276     * @return the value of holder with the specified bits set or
277     *  cleared
278     */
279    public byte setByteBoolean(final byte holder, final boolean flag) {
280        return flag ? setByte(holder) : clearByte(holder);
281    }
282
283}