    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    }