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