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