001    /** 
002     * 
003     * Copyright 2004 Protique Ltd
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * 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     **/
018    package org.activemq.util;
019    
020    import java.io.DataInput;
021    import java.io.DataOutput;
022    import java.io.IOException;
023    
024    /**
025     * Simple BitArray to enable setting multiple boolean values efficently Used instead of BitSet because BitSet does not
026     * allow for efficent serialization.
027     * Will store up to 64 boolean values
028     * 
029     * @version $Revision: 1.1.1.1 $
030     */
031    public class BitArray {
032        static final int LONG_SIZE = 64;
033        static final int INT_SIZE = 32;
034        static final int SHORT_SIZE = 16;
035        static final int BYTE_SIZE = 8;
036        private static final long[] BIT_VALUES = {0x0000000000000001L, 0x0000000000000002L, 0x0000000000000004L,
037                                                  0x0000000000000008L, 0x0000000000000010L, 0x0000000000000020L, 0x0000000000000040L, 0x0000000000000080L,
038                                                  0x0000000000000100L, 0x0000000000000200L, 0x0000000000000400L, 0x0000000000000800L, 0x0000000000001000L,
039                                                  0x0000000000002000L, 0x0000000000004000L, 0x0000000000008000L, 0x0000000000010000L, 0x0000000000020000L,
040                                                  0x0000000000040000L, 0x0000000000080000L, 0x0000000000100000L, 0x0000000000200000L, 0x0000000000400000L,
041                                                  0x0000000000800000L, 0x0000000001000000L, 0x0000000002000000L, 0x0000000004000000L, 0x0000000008000000L,
042                                                  0x0000000010000000L, 0x0000000020000000L, 0x0000000040000000L, 0x0000000080000000L, 0x0000000100000000L,
043                                                  0x0000000200000000L, 0x0000000400000000L, 0x0000000800000000L, 0x0000001000000000L, 0x0000002000000000L,
044                                                  0x0000004000000000L, 0x0000008000000000L, 0x0000010000000000L, 0x0000020000000000L, 0x0000040000000000L,
045                                                  0x0000080000000000L, 0x0000100000000000L, 0x0000200000000000L, 0x0000400000000000L, 0x0000800000000000L,
046                                                  0x0001000000000000L, 0x0002000000000000L, 0x0004000000000000L, 0x0008000000000000L, 0x0010000000000000L,
047                                                  0x0020000000000000L, 0x0040000000000000L, 0x0080000000000000L, 0x0100000000000000L, 0x0200000000000000L,
048                                                  0x0400000000000000L, 0x0800000000000000L, 0x1000000000000000L, 0x2000000000000000L, 0x4000000000000000L,
049                                                  0x8000000000000000L};
050        private long bits;
051        private int length;
052    
053        /**
054         * @return the length of bits set
055         */
056        public int length() {
057            return length;
058        }
059    
060        /**
061         * @return the long containing the bits
062         */
063        public long getBits() {
064            return bits;
065        }
066    
067        /**
068         * set the boolean value at the index
069         *
070         * @param index
071         * @param flag
072         * @return the old value held at this index
073         */
074        public boolean set(int index, boolean flag) {
075            length = Math.max(length, index + 1);
076            boolean oldValue = (bits & BIT_VALUES[index]) != 0;
077            if (flag) {
078                bits |= BIT_VALUES[index];
079            }
080            else if (oldValue) {
081                bits &= ~(BIT_VALUES[index]);
082            }
083            return oldValue;
084        }
085    
086        /**
087         * @param index
088         * @return the boolean value at this index
089         */
090        public boolean get(int index) {
091            return (bits & BIT_VALUES[index]) != 0;
092        }
093        
094        /**
095         * reset all the bit values to false
096         */
097        public void reset(){
098            bits = 0;
099        }
100        
101        /**
102         * reset all the bits to the value supplied
103         * @param bits
104         */
105        public void reset(long bits){
106            this.bits = bits;
107        }
108    
109        /**
110         * write the bits to an output stream
111         *
112         * @param dataOut
113         * @throws IOException
114         */
115        public void writeToStream(DataOutput dataOut) throws IOException {
116            dataOut.writeByte(length);
117            if (length <= BYTE_SIZE) {
118                dataOut.writeByte((int) bits);
119            }
120            else if (length <= SHORT_SIZE) {
121                dataOut.writeShort((short) bits);
122            }
123            else if (length <= INT_SIZE) {
124                dataOut.writeInt((int) bits);
125            }
126            else {
127                dataOut.writeLong(bits);
128            }
129        }
130    
131        /**
132         * read the bits from an input stream
133         *
134         * @param dataIn
135         * @throws IOException
136         */
137        public void readFromStream(DataInput dataIn) throws IOException {
138            length = dataIn.readByte();
139            if (length <= BYTE_SIZE) {
140                bits = (long) dataIn.readByte();
141            }
142            else if (length <= SHORT_SIZE) {
143                bits = (long) dataIn.readShort();
144            }
145            else if (length <= INT_SIZE) {
146                bits = (int) dataIn.readInt();
147            }
148            else {
149                bits = dataIn.readLong();
150            }
151        }
152    }