1 /* BitString.java -- Java representation of the BIT STRING type. 2 Copyright (C) 2003 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 19 02111-1307 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.java.security.der; 40 41 import java.math.BigInteger; 42 import java.util.Arrays; 43 44 /** 45 * Immutable representation of a bit string, which is equivalent to a 46 * byte array except some number of the rightmost bits are ignored. For 47 * example, this could be the bit string: 48 * 49 * <pre> 00010101 11101101 11010xxx</pre> 50 * 51 * <p>Where the "xxx" represents three bits that should be ignored, and 52 * can have any value. 53 * 54 * @author Casey Marshall (rsdio@metastatic.org) 55 */ 56 public class BitString implements Cloneable, Comparable, java.io.Serializable 57 { 58 59 // Fields. 60 // ------------------------------------------------------------------------ 61 62 /** The bits themselves. */ 63 private final byte[] bytes; 64 65 /** 66 * The exportable byte array. This array has the ignored bits 67 * removed. 68 */ 69 private transient byte[] externBytes; 70 71 /** The number of bits ignored at the end of the byte array. */ 72 private final int ignoredBits; 73 74 /** This bit string as a boolean array. */ 75 private transient boolean[] boolVal; 76 77 // Constructors. 78 // ------------------------------------------------------------------------ 79 80 /** 81 * Create a new bit string, shifting the given byte array if needed. 82 * 83 * @param bytes The byte array holding the bit string. 84 * @param ignoredBits The number of bits to ignore. 85 * @param doShift Pass true in this parameter if the byte array has 86 * not yet been shifted left by <i>ignoredBits</i>. 87 * @throws IllegalArgumentException If <i>ignoredBits</i> is negative 88 * or greater than 7. 89 * @throws NullPointerException If <i>bytes</i> is null. 90 */ BitString(byte[] bytes, int ignoredBits, boolean doShift)91 public BitString(byte[] bytes, int ignoredBits, boolean doShift) 92 { 93 this(bytes, 0, bytes.length, ignoredBits, doShift); 94 } 95 96 /** 97 * Create a new bit string, shifting the given byte array if needed. 98 * 99 * @param bytes The byte array holding the bit string. 100 * @param offset The offset where the meaningful bytes begin. 101 * @param length The number of meaningful bytes. 102 * @param ignoredBits The number of bits to ignore. 103 * @param doShift Pass true in this parameter if the byte array has 104 * not yet been shifted left by <i>ignoredBits</i>. 105 * @throws IllegalArgumentException If <i>ignoredBits</i> is negative 106 * or greater than 7. 107 * @throws NullPointerException If <i>bytes</i> is null. 108 */ BitString(byte[] bytes, int offset, int length, int ignoredBits, boolean doShift)109 public BitString(byte[] bytes, int offset, int length, 110 int ignoredBits, boolean doShift) 111 { 112 if (ignoredBits < 0 || ignoredBits > 7) 113 throw new IllegalArgumentException(); 114 if (bytes == null) 115 throw new NullPointerException(); 116 if (doShift && ignoredBits > 0) 117 { 118 this.externBytes = new byte[length]; 119 System.arraycopy(bytes, offset, externBytes, 0, length); 120 this.bytes = new BigInteger(externBytes).shiftLeft(ignoredBits) 121 .toByteArray(); 122 } 123 else 124 { 125 this.bytes = new byte[length]; 126 System.arraycopy(bytes, offset, this.bytes, 0, length); 127 } 128 this.ignoredBits = ignoredBits; 129 } 130 131 /** 132 * Create a new bit string. 133 * 134 * @param bytes The byte array holding the bit string. 135 * @param offset The offset where the meaningful bytes begin. 136 * @param length The number of meaningful bytes. 137 * @param ignoredBits The number of bits to ignore. 138 * @throws IllegalArgumentException If <i>ignoredBits</i> is negative 139 * or greater than 7. 140 * @throws NullPointerException If <i>bytes</i> is null. 141 */ BitString(byte[] bytes, int offset, int length, int ignoredBits)142 public BitString(byte[] bytes, int offset, int length, int ignoredBits) 143 { 144 this(bytes, offset, length, ignoredBits, false); 145 } 146 147 /** 148 * Create a new bit string. 149 * 150 * @param bytes The byte array holding the bit string. 151 * @param ignoredBits The number of bits to ignore. 152 * @throws IllegalArgumentException If <i>ignoredBits</i> is negative 153 * or greater than 7. 154 * @throws NullPointerException If <i>bytes</i> is null. 155 */ BitString(byte[] bytes, int ignoredBits)156 public BitString(byte[] bytes, int ignoredBits) 157 { 158 this(bytes, 0, bytes.length, ignoredBits, false); 159 } 160 161 /** 162 * Create a new bit string. 163 * 164 * @param bytes The byte array holding the bit string. 165 * @param offset The offset where the meaningful bytes begin. 166 * @param length The number of meaningful bytes. 167 * @throws NullPointerException If <i>bytes</i> is null. 168 */ BitString(byte[] bytes, int offset, int length)169 public BitString(byte[] bytes, int offset, int length) 170 { 171 this(bytes, offset, length, 0, false); 172 } 173 174 /** 175 * Create a new bit string. 176 * 177 * @param bytes The byte array holding the bit string. 178 * @throws NullPointerException If <i>bytes</i> is null. 179 */ BitString(byte[] bytes)180 public BitString(byte[] bytes) 181 { 182 this(bytes, 0, bytes.length, 0, false); 183 } 184 185 // Instance methods. 186 // ------------------------------------------------------------------------ 187 188 /** 189 * Return this bit string as a byte array, with the ignored bits 190 * trimmed off. The byte array is cloned every time this method is 191 * called to prevent modification. 192 * 193 * @return The trimmed byte array. 194 */ toByteArray()195 public byte[] toByteArray() 196 { 197 if (ignoredBits == 0) 198 return (byte[]) bytes.clone(); 199 if (externBytes == null) 200 externBytes = new BigInteger(bytes).shiftRight(ignoredBits).toByteArray(); 201 return (byte[]) externBytes.clone(); 202 } 203 204 /** 205 * Returns this bit string as a byte array, with the ignored bits 206 * present. The byte array is cloned every time this method is 207 * called to prevent modification. 208 * 209 * @return The byte array. 210 */ getShiftedByteArray()211 public byte[] getShiftedByteArray() 212 { 213 return (byte[]) bytes.clone(); 214 } 215 216 /** 217 * Returns the number of ignored bits. 218 * 219 * @return The number of ignored bits. 220 */ getIgnoredBits()221 public int getIgnoredBits() 222 { 223 return ignoredBits; 224 } 225 226 /** 227 * Returns the size, in bits, of this bit string. 228 * 229 * @return The size of this bit string. 230 */ size()231 public int size() 232 { 233 return (bytes.length << 3) - ignoredBits; 234 } 235 236 /** 237 * Return this bit string as a boolean array. The value returned is of 238 * size {@link #size()}, and each <code>true</code> value 239 * corresponding to each "1" in this bit string. The boolean array is 240 * cloned before it is returned. 241 * 242 * @return The boolean array. 243 */ toBooleanArray()244 public boolean[] toBooleanArray() 245 { 246 if (boolVal == null) 247 { 248 boolVal = new boolean[size()]; 249 for (int i = 0, j = 7, k = 0; i < boolVal.length; i++) 250 { 251 boolVal[i] = (bytes[k] & 1 << j--) != 0; 252 if (j < 0) 253 { 254 j = 7; 255 k++; 256 } 257 } 258 } 259 return (boolean[]) boolVal.clone(); 260 } 261 clone()262 public Object clone() 263 { 264 try 265 { 266 return super.clone(); 267 } 268 catch (CloneNotSupportedException cce) 269 { 270 throw new InternalError(cce.getMessage()); 271 } 272 } 273 compareTo(Object o)274 public int compareTo(Object o) 275 { 276 BitString that = (BitString) o; 277 if (this.equals(that)) 278 return 0; 279 if (this.bytes.length != that.bytes.length) 280 return (this.bytes.length < that.bytes.length) ? -1 : 1; 281 if (this.ignoredBits != that.ignoredBits) 282 return (this.ignoredBits < that.ignoredBits) ? -1 : 1; 283 for (int i = 0; i < this.bytes.length; i++) 284 if (this.bytes[i] != that.bytes[i]) 285 return (this.bytes[i] < that.bytes[i]) ? -1 : 1; 286 return 0; // not reached. 287 } 288 equals(Object o)289 public boolean equals(Object o) 290 { 291 if (this == o) 292 return true; 293 BitString that = (BitString) o; 294 // True for cloned instances. 295 if (this.bytes == that.bytes && this.ignoredBits == that.ignoredBits) 296 return true; 297 if (this.ignoredBits == that.ignoredBits) 298 return Arrays.equals(this.bytes, that.bytes); 299 return false; 300 } 301 toString()302 public String toString() 303 { 304 StringBuffer sb = new StringBuffer(); 305 for (int i = 0, j = 7, k = 0; i < size(); i++) 306 { 307 sb.append((bytes[k] & 1 << j) != 0 ? "1" : "0"); 308 j--; 309 if (j < 0) 310 { 311 j = 7; 312 k++; 313 } 314 } 315 return sb.toString(); 316 } 317 } 318