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     */
017    package org.apache.commons.lang3;
018    
019    /**
020     * <p>Operations on bit-mapped fields.</p>
021     *
022     * @since 2.0
023     * @version $Id: BitField.java 1088899 2011-04-05 05:31:27Z bayard $
024     */
025    public 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(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(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(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(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(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(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(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(int holder, 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(short holder, 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(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(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(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(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(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(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(int holder, 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(short holder, 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(byte holder, boolean flag) {
280            return flag ? setByte(holder) : clearByte(holder);
281        }
282    
283    }