1 21 22 package org.apache.derby.iapi.services.io; 23 24 import org.apache.derby.iapi.services.sanity.SanityManager; 25 26 import java.io.InputStream ; 27 import java.io.ObjectOutput ; 28 import java.io.ObjectInput ; 29 import java.io.IOException ; 30 31 36 37 public final class FormatableBitSet implements Formatable, Cloneable 38 { 39 40 53 54 70 private byte[] value; 71 private short bitsInLastByte; 72 73 private transient int lengthAsBits; 74 75 78 public FormatableBitSet() 79 { 80 } 81 82 85 public FormatableBitSet(int numBits) 86 { 87 initializeBits(numBits); 88 } 89 90 private void initializeBits(int numBits) 91 { 92 int numBytes = numBytesFromBits(numBits); 93 94 value = new byte[numBytes]; 96 bitsInLastByte = numBitsInLastByte(numBits); 97 lengthAsBits = numBits; 98 } 99 100 106 public FormatableBitSet(byte[] newValue) 107 { 108 value = newValue; 109 bitsInLastByte = 8; 110 lengthAsBits = calculateLength(newValue.length); 111 } 112 113 119 public FormatableBitSet(byte[] newValue, int numBits) 120 { 121 bitsInLastByte = numBitsInLastByte(numBits); 122 lengthAsBits = numBits; 123 124 int lenInBytes = numBytesFromBits(numBits); 125 126 if (lenInBytes == newValue.length) { 127 value = newValue; 128 } else { 129 value = new byte[lenInBytes]; 130 System.arraycopy(newValue, 0, value, 0, newValue.length); 131 } 132 } 133 134 139 public FormatableBitSet (FormatableBitSet original) 140 { 141 if (SanityManager.DEBUG) 142 SanityManager.ASSERT( 143 original != null, "cannot make copy from a null FormatableBitSet"); 144 145 bitsInLastByte = original.bitsInLastByte; 146 lengthAsBits = original.lengthAsBits; 147 148 int lenInBytes = FormatableBitSet.numBytesFromBits(original.lengthAsBits); 149 value = new byte[lenInBytes]; 150 if (lenInBytes > 0) 151 System.arraycopy(original.value, 0, value, 0, lenInBytes); 152 } 153 154 157 public Object clone() 158 { 159 return new FormatableBitSet(this); 160 } 161 162 163 168 public int getLengthInBytes() 169 { 170 if (value == null) 171 { 172 return 0; 173 } 174 175 return FormatableBitSet.numBytesFromBits(lengthAsBits); 176 } 177 178 190 public int getLength() { 191 return lengthAsBits; 192 } 193 194 private int calculateLength(int realByteLength) 195 { 196 if (realByteLength == 0) 197 { 198 return 0; 199 } 200 201 return ((realByteLength - 1) * 8) + bitsInLastByte; 202 } 203 204 209 public int size() 210 { 211 return getLength(); 212 } 213 214 219 220 public byte[] getByteArray() 221 { 222 if (value == null) 223 return null; 224 225 int realByteLength = getLengthInBytes(); 228 229 if (value.length != realByteLength) { 232 byte[] data = new byte[realByteLength]; 233 System.arraycopy(value, 0, data, 0, realByteLength); 234 235 value = data; 236 } 237 238 return value; 239 } 240 241 246 public boolean isNull() 247 { 248 return this.value == null; 249 } 250 251 261 public void grow(int n) 262 { 263 if (n <= this.getLength()) 264 return; 265 266 if (value == null) 267 { 268 initializeBits(n); 269 return; 270 } 271 272 int delta = n - this.getLength(); 273 274 275 int oldNumBytes = getLengthInBytes(); 276 277 281 if ((oldNumBytes != 0) && 282 (8 - this.bitsInLastByte) >= delta) 283 { 284 this.bitsInLastByte += delta; 285 lengthAsBits = n; 286 return; 287 } 288 289 int newNumBytes = FormatableBitSet.numBytesFromBits(n); 290 291 if (newNumBytes <= value.length) { 293 for (int i = oldNumBytes; i < newNumBytes; i++) 295 value[i] = 0; 296 } else { 297 298 299 303 byte[] newValue = new byte[newNumBytes]; 304 305 System.arraycopy(value, 0, newValue, 0, oldNumBytes); 306 307 value = newValue; 308 } 309 bitsInLastByte = numBitsInLastByte(n); 310 lengthAsBits = n; 311 } 312 313 320 public FormatableBitSet shrink(int n) 321 { 322 int numBytes; 323 int lastByteNum; 324 325 329 if (SanityManager.DEBUG) 330 { 331 if (value == null) 332 { 333 SanityManager.THROWASSERT("Attempt to shrink a null Bit"+ 334 " -- caller should have known better probably"); 335 return null; 336 } 337 } 338 339 if (n >= this.getLength()) 340 { 341 return this; 342 } 343 344 345 lastByteNum = numBytesFromBits(n) - 1; 346 bitsInLastByte = numBitsInLastByte(n); 347 lengthAsBits = n; 348 349 353 if (bitsInLastByte != 8) 354 { 355 value[lastByteNum] &= 0xFF00 >> bitsInLastByte; 356 } 357 358 return this; 359 } 360 361 367 368 379 public boolean equals(FormatableBitSet other) 380 { 381 if (this.getLength() != other.getLength()) 382 { 383 return false; 384 } 385 386 return (this.compare(other) == 0); 387 } 388 389 408 public int compare(FormatableBitSet other) 409 { 410 411 int otherCount, thisCount; 412 int otherLen, thisLen; 413 byte[] otherb; 414 415 otherb = other.value; 416 419 if (this.value == null || otherb == null) 420 { 421 if (this.value != null) return 1; 423 if (otherb != null) return -1; 425 return 0; } 427 428 otherLen = other.getLengthInBytes(); 429 thisLen = getLengthInBytes(); 430 for (otherCount = 0, thisCount = 0; 431 otherCount < otherLen && thisCount < thisLen; 432 otherCount++, thisCount++) 433 { 434 if (otherb[otherCount] != this.value[thisCount]) 435 break; 436 } 437 438 442 if ((otherCount == otherLen) && (thisCount == thisLen)) 443 { 444 if (this.getLength() == other.getLength()) 445 { 446 return 0; 447 } 448 449 454 return (other.getLength() < this.getLength()) ? 1 : -1; 455 } 456 457 if (otherCount == otherLen) 458 { 459 return 1; 460 } 461 else if (thisCount == thisLen) 462 { 463 return -1; 464 } 465 else 466 { 467 473 int otherInt, thisInt; 474 475 otherInt = (int)otherb[otherCount]; 476 otherInt &= (0x100 - 1); 477 478 thisInt = (int)this.value[thisCount]; 479 thisInt &= (0x100 - 1); 480 481 return (thisInt > otherInt) ? 1 : -1; 482 483 } 484 } 485 486 494 public FormatableBitSet concatenate(FormatableBitSet other) 495 { 496 int newLen; 497 int otherLen; 498 int prevLen; 499 int prevLenBytes; 500 int newLenBytes; 501 int otherLenBytes; 502 int i, j; 503 byte[] newValue; 504 byte[] otherValue; 505 int shiftBits; 506 int inByte; 507 508 509 prevLen = this.getLength(); 510 prevLenBytes = this.getLengthInBytes(); 511 otherLen = other.getLength(); 512 otherValue = other.getByteArray(); 513 otherLenBytes = other.getLengthInBytes(); 514 newLen = prevLen + otherLen; 515 newLenBytes = numBytesFromBits(newLen); 516 newValue = new byte[newLenBytes]; 517 518 519 523 for (i = 0; i < prevLenBytes; i++) 524 { 525 newValue[i] = this.value[i]; 526 } 527 528 535 shiftBits = (prevLen == 0) ? 8 : this.bitsInLastByte; 536 for (j = 0; j < otherLenBytes; j++, i++) 537 { 538 if (shiftBits == 8) 539 { 540 newValue[i] = otherValue[j]; 541 } 542 else 543 { 544 548 inByte = (int)otherValue[j]; 549 550 554 inByte &= (0x100 - 1); 555 556 560 newValue[i-1] |= (inByte >>> shiftBits); 561 562 566 if (i < newLenBytes) 567 { 568 newValue[i] |= (inByte << (8 - shiftBits)); 569 } 570 } 571 } 572 573 return new FormatableBitSet(newValue, newLen); 574 } 575 576 582 public int hashCode() 583 { 584 if( null == value) 585 return 0; 586 587 int code = 0; 588 int i; 589 int shift = 0; 590 591 int byteLength = getLengthInBytes(); 592 for( i = 0; i < byteLength; i++) 593 { 594 code ^= (value[i] & 0xff)<<shift; 595 shift += 8; 596 if( 32 <= shift) 597 shift = 0; 598 } 599 return code; 600 } 601 602 608 public final boolean isSet(int position) 609 { 610 if (SanityManager.DEBUG) 611 { 612 if (position >= this.getLength()) 613 { 614 SanityManager.THROWASSERT( 615 "Attempt to get a bit position (" + position + 616 ")" + 617 "that exceeds the max length (" + this.getLength() + ")"); 618 } 619 } 620 621 try { 622 623 int bytepos = position / 8; 624 int bitpos = 7 - (position % 8); 625 626 return ((value[bytepos] & (1 << bitpos)) != 0); 627 628 } catch (ArrayIndexOutOfBoundsException e) { 629 return false; 632 } 633 } 634 635 641 public final boolean get(int position) 642 { 643 return isSet(position); 644 } 645 646 652 public void set(int position) 653 { 654 655 if (SanityManager.DEBUG) 656 { 657 if (position >= this.getLength()) 658 { 659 SanityManager.THROWASSERT( 660 "Attempt to set a bit position that exceeds the max length (" 661 + this.getLength() + ")"); 662 } 663 } 664 665 if (position >= getLength()) 668 grow(position); 669 670 int bytepos = position / 8; 671 int bitpos = 7 - (position % 8); 672 673 value[bytepos] |= (1 << bitpos); 674 } 675 676 682 public void clear(int position) 683 { 684 int bytepos; 685 int bitpos; 686 687 if (SanityManager.DEBUG) 688 { 689 if (position >= this.getLength()) 690 { 691 SanityManager.THROWASSERT( 692 "Attempt to set a bit position that exceeds the max length (" 693 + this.getLength() + ")"); 694 } 695 } 696 697 if (position >= getLength()) 700 grow(position); 701 702 bytepos = position / 8; 703 bitpos = 7 - (position % 8); 704 705 value[bytepos] &= ~(1 << bitpos); 706 } 707 708 711 public void clear() 712 { 713 if (value == null) 714 return; 715 716 int byteLength = getLengthInBytes(); 717 for (int ix=0; ix < byteLength; ix++) 718 value[ix] = 0; 719 } 720 721 722 730 protected static int 731 numBytesFromBits(int bits) 732 { 733 return (bits == 0) ? 0 : ((bits - 1) / 8) + 1; 734 } 735 736 744 private static short 745 numBitsInLastByte(int bits) 746 { 747 int modulo = bits % 8; 748 return (short)((modulo == 0) ? 749 ((bits == 0) ? 0 : 8) : 750 modulo); 751 } 752 753 760 private static byte 761 hexCharToByte(char hexChar) 762 { 763 byte byteValue; 764 765 switch (hexChar) 766 { 767 case '0': 768 byteValue = 0; 769 break; 770 771 case '1': 772 byteValue = 1; 773 break; 774 775 case '2': 776 byteValue = 2; 777 break; 778 779 case '3': 780 byteValue = 3; 781 break; 782 783 case '4': 784 byteValue = 4; 785 break; 786 787 case '5': 788 byteValue = 5; 789 break; 790 791 case '6': 792 byteValue = 6; 793 break; 794 795 case '7': 796 byteValue = 7; 797 break; 798 799 case '8': 800 byteValue = 8; 801 break; 802 803 case '9': 804 byteValue = 9; 805 break; 806 807 case 'a': 808 case 'A': 809 byteValue = 0xA; 810 break; 811 812 case 'b': 813 case 'B': 814 byteValue = 0xB; 815 break; 816 817 case 'c': 818 case 'C': 819 byteValue = 0xC; 820 break; 821 822 case 'd': 823 case 'D': 824 byteValue = 0xD; 825 break; 826 827 case 'e': 828 case 'E': 829 byteValue = 0xE; 830 break; 831 832 case 'f': 833 case 'F': 834 byteValue = 0xF; 835 break; 836 837 default: 838 if (SanityManager.DEBUG) 839 { 840 SanityManager.THROWASSERT("illegal char = " + hexChar); 841 } 842 throw new IllegalArgumentException (); 843 } 844 845 return byteValue; 846 } 847 848 private static char[] decodeArray = {'0', '1', '2', '3', '4', '5', '6', '7', 849 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 850 851 857 public String toString() 858 { 859 char[] outChars; 860 int inPosition; 861 int outPosition; 862 int inByte; 863 864 if (value == null) 865 { 866 return null; 867 } 868 { 869 StringBuffer str = new StringBuffer (getLength()*8*3); 871 str.append("{"); 872 boolean first = true; 873 for (inPosition = 0; inPosition < getLength(); inPosition++) 874 { 875 if (isSet(inPosition)) 876 { 877 if (!first) 878 str.append(", "); 879 first = false; 880 str.append(inPosition); 881 } 882 } 883 str.append("}"); 884 return new String (str); 885 } 886 } 887 888 889 890 895 public static int maxBitsForSpace(int numBytes) 896 { 897 return (numBytes - 4)*8; 898 899 } 900 901 907 public int anySetBit() 908 { 909 int numbytes = getLengthInBytes(); 910 int bitpos; 911 912 for (int i = 0; i < numbytes-1; i++) 913 { 914 if (value[i] != 0) 915 { 916 for (int j = 0; j < 8; j++) 917 { 918 bitpos = 7-j; 919 if (((1 << bitpos) & value[i]) != 0) 920 return ((i*8)+j); 921 } 922 } 923 } 924 925 926 byte mask = (byte)(0xFF << (8-bitsInLastByte)); 928 if ((value[numbytes-1] & mask) != 0) 929 { 930 for (int j = 0; j < bitsInLastByte; j++) 931 { 932 bitpos = 7-j; 933 if (((1 << bitpos) & value[numbytes-1]) != 0) 934 return ((numbytes-1)*8)+j; 935 } 936 } 937 938 return -1; 939 } 940 941 951 public int anySetBit(int beyondBit) 952 { 953 if (SanityManager.DEBUG) 954 { 955 if (beyondBit >= this.getLength()) 956 SanityManager.THROWASSERT( 957 "Attempt to access bit position that exceeds the max length (" 958 + this.getLength() + ")"); 959 } 960 961 int startingBit = (beyondBit+1); 962 963 if (startingBit >= this.getLength()) 965 return -1; 966 967 int numbytes = getLengthInBytes(); 968 int startingByte = startingBit / 8; 969 int startingBitpos = startingBit % 8; 970 int bitpos; 971 byte mask; 972 973 mask = (byte)(0xFF >> startingBitpos); 976 977 if (startingByte == numbytes-1) mask &= (byte)(0xFF << (8-bitsInLastByte)); 979 980 if ((value[startingByte] & mask ) != 0) 981 { 982 for (int j = startingBitpos; j < 8; j++) 985 { 986 if (SanityManager.DEBUG) 987 { 988 if (startingByte == numbytes-1) 989 SanityManager.ASSERT(j < bitsInLastByte, 990 "going beyond the last bit"); 991 } 992 bitpos = 7-j; 993 if (((1 << bitpos) & value[startingByte]) != 0) 994 { 995 return (startingByte*8+j); 996 } 997 } 998 } 999 1000 for (int i = (startingByte+1); i < numbytes-1; i++) 1001 { 1002 if (value[i] != 0) 1003 { 1004 for (int j = 0; j < 8; j++) 1005 { 1006 bitpos = 7-j; 1007 if (((1 << bitpos) & value[i]) != 0) 1008 { 1009 return ((i*8)+j); 1010 } 1011 } 1012 } 1013 } 1014 1015 if (startingByte != numbytes-1) 1018 { 1019 mask = (byte)(0xFF << (8-bitsInLastByte)); 1020 1021 if ((value[numbytes-1] & mask) != 0) 1022 { 1023 for (int j = 0; j < bitsInLastByte; j++) 1024 { 1025 bitpos = 7-j; 1026 if (((1 << bitpos) & value[numbytes-1]) != 0) 1027 { 1028 return ((numbytes-1)*8)+j; 1029 } 1030 } 1031 } 1032 } 1033 1034 return -1; 1035 1036 } 1037 1038 1043 public void or(FormatableBitSet otherBit) 1044 { 1045 if (otherBit == null || otherBit.getLength() == 0) 1046 return; 1047 1048 int otherLength = otherBit.getLength(); 1049 1050 if (otherLength > getLength()) 1051 grow(otherLength); 1053 if (otherBit instanceof FormatableBitSet) 1054 { 1055 FormatableBitSet ob = (FormatableBitSet)otherBit; 1057 int obByteLen = ob.getLengthInBytes(); 1058 for (int i = 0; i < obByteLen-1; i++) 1059 value[i] |= ob.value[i]; 1060 1061 for (int i = (obByteLen-1)*8; i < otherLength; i++) 1063 if (otherBit.isSet(i)) 1064 set(i); 1065 } 1066 else 1067 { 1068 1072 for (int i = 0; i < otherLength; i++) 1073 { 1074 if (otherBit.isSet(i)) 1075 set(i); 1076 } 1077 } 1078 } 1079 1080 1085 public void and(FormatableBitSet otherBit) 1086 { 1087 if (SanityManager.DEBUG) 1088 SanityManager.ASSERT(otherBit != null, "cannot AND null with a FormatableBitSet"); 1089 1090 int otherLength = otherBit.getLength(); 1091 1092 if (otherLength > getLength()) 1094 grow(otherLength); 1096 if (otherLength < getLength()) 1097 { 1098 int startingByte = (otherLength * 8) + 1; 1100 int len = getLengthInBytes(); 1101 for (int i = startingByte; i < len; i++) 1102 value[i] = 0; 1103 1104 for (int i = otherLength; i < startingByte*8; i++) 1105 { 1106 if (i < getLength()) 1107 clear(i); 1108 else 1109 break; 1110 } 1111 } 1112 1113 if (otherLength == 0) 1114 return; 1115 1116 int length = otherBit.getLengthInBytes() < getLengthInBytes() ? 1117 otherBit.getLengthInBytes() : getLengthInBytes(); 1118 1119 for (int i = 0; i < length; i++) 1120 value[i] &= otherBit.value[i]; 1121 } 1122 1123 1127 public void xor(FormatableBitSet set) 1128 { 1129 if (SanityManager.DEBUG) 1130 { 1131 if (getLength() != set.getLength()) 1132 { 1133 SanityManager.THROWASSERT("getLength() (" + getLength() + 1134 ") and set.getLength() (" + 1135 set.getLength() + 1136 ") expected to be the same"); 1137 } 1138 } 1139 1140 int setLength = set.getLength(); 1141 for (int i = setLength; i-- > 0; ) 1142 { 1143 if (isSet(i) && set.isSet(i)) 1144 { 1145 clear(i); 1146 } 1147 else if (isSet(i) || set.isSet(i)) 1148 { 1149 set(i); 1150 } 1151 } 1152 } 1153 1154 1159 public int getNumBitsSet() 1160 { 1161 int count = 0; 1162 1163 for (int index = getLength() - 1; index >= 0; index--) 1164 { 1165 if (isSet(index)) 1166 { 1167 count++; 1168 } 1169 } 1170 1171 return count; 1172 } 1173 1174 1186 public void writeExternal(ObjectOutput out) throws IOException 1187 { 1188 if (SanityManager.DEBUG) 1190 SanityManager.ASSERT(value != null); 1191 1192 out.writeInt(getLength()); 1193 int byteLen = getLengthInBytes(); 1194 if (byteLen > 0) 1195 { 1196 out.write(value, 0, byteLen); 1197 } 1198 } 1199 1200 1214 public void readExternal(ObjectInput in) throws IOException 1215 { 1216 int lenInBits; 1217 int lenInBytes; 1218 1219 lenInBits = in.readInt(); 1220 1221 lenInBytes = FormatableBitSet.numBytesFromBits(lenInBits); 1222 1223 1224 1235 1236 value = new byte[lenInBytes]; 1237 1238 in.readFully(value); 1239 1240 bitsInLastByte = numBitsInLastByte(lenInBits); 1241 1242 lengthAsBits = lenInBits; 1243 } 1244 1245 public void readExternalFromArray(ArrayInputStream in) throws IOException 1246 { 1247 int lenInBits = in.readInt(); 1248 1249 int lenInBytes = FormatableBitSet.numBytesFromBits(lenInBits); 1250 1251 value = new byte[lenInBytes]; 1252 1253 in.readFully(value); 1254 1255 bitsInLastByte = numBitsInLastByte(lenInBits); 1256 1257 lengthAsBits = lenInBits; 1258 } 1259 1260 1265 public int getTypeFormatId() { return StoredFormatIds.BITIMPL_V01_ID; } 1266} 1267 | Popular Tags |