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