📄 formatablebitset.java
字号:
* Bit get -- alias for isSet() * * @param position the bit to check * */ public final boolean get(int position) { return isSet(position); } /** * Bit set * * @param position the bit to set * */ public void set(int position) { if (SanityManager.DEBUG) { if (position >= this.getLength()) { SanityManager.THROWASSERT( "Attempt to set a bit position that exceeds the max length (" + this.getLength() + ")"); } } // Should not happen, handle it just in case not all cases are tested // by insane server. if (position >= getLength()) grow(position); int bytepos = position / 8; int bitpos = 7 - (position % 8); value[bytepos] |= (1 << bitpos); } /** * Bit clear * * @param position the bit to clear * */ public void clear(int position) { int bytepos; int bitpos; if (SanityManager.DEBUG) { if (position >= this.getLength()) { SanityManager.THROWASSERT( "Attempt to set a bit position that exceeds the max length (" + this.getLength() + ")"); } } // Should not happen, handle it just in case not all cases are tested // by insane server. if (position >= getLength()) grow(position); bytepos = position / 8; bitpos = 7 - (position % 8); value[bytepos] &= ~(1 << bitpos); } /** Clear all the bits in this FormatableBitSet */ public void clear() { if (value == null) return; int byteLength = getLengthInBytes(); for (int ix=0; ix < byteLength; ix++) value[ix] = 0; } /** * Figure out how many bytes are needed to * store the input number of bits. * * @param bits bits * * @return the number of bytes */ protected static int numBytesFromBits(int bits) { return (bits == 0) ? 0 : ((bits - 1) / 8) + 1; } /** * Figure out how many bits are in the last * byte from the total number of bits. * * @param bits bits * * @return the number of bits */ private static short numBitsInLastByte(int bits) { int modulo = bits % 8; return (short)((modulo == 0) ? ((bits == 0) ? 0 : 8) : modulo); } /** * Translate a hex character to a byte. * * @param hexChar A character with the value [0-9a-fA-F]. * * @return A byte with the numeric value corresponding to the hex character */ private static byte hexCharToByte(char hexChar) { byte byteValue; switch (hexChar) { case '0': byteValue = 0; break; case '1': byteValue = 1; break; case '2': byteValue = 2; break; case '3': byteValue = 3; break; case '4': byteValue = 4; break; case '5': byteValue = 5; break; case '6': byteValue = 6; break; case '7': byteValue = 7; break; case '8': byteValue = 8; break; case '9': byteValue = 9; break; case 'a': case 'A': byteValue = 0xA; break; case 'b': case 'B': byteValue = 0xB; break; case 'c': case 'C': byteValue = 0xC; break; case 'd': case 'D': byteValue = 0xD; break; case 'e': case 'E': byteValue = 0xE; break; case 'f': case 'F': byteValue = 0xF; break; default: if (SanityManager.DEBUG) { SanityManager.THROWASSERT("illegal char = " + hexChar); } throw new IllegalArgumentException(); } return byteValue; }private static char[] decodeArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * Format the string into BitSet format: {0, 2, 4, 8} if bits 0, 2, 4, 8 * are set. * * @return A new String containing the formatted Bit value */ public String toString() { char[] outChars; int inPosition; int outPosition; int inByte; if (value == null) { return null; } { // give it a reasonable size StringBuffer str = new StringBuffer(getLength()*8*3); str.append("{"); boolean first = true; for (inPosition = 0; inPosition < getLength(); inPosition++) { if (isSet(inPosition)) { if (!first) str.append(", "); first = false; str.append(inPosition); } } str.append("}"); return new String(str); } } /** * Statically calculates how many bits can fit into the number of * bytes if this Bit object is externalized. Only valid for this * implementation of Bit. */ public static int maxBitsForSpace(int numBytes) { return (numBytes - 4)*8; } /** * If any bit is set, return the bit number of a bit that is set. * If no bit is set, return -1; * * @return the bit number of a bit that is set, or -1 if no bit is set */ public int anySetBit() { int numbytes = getLengthInBytes(); int bitpos; for (int i = 0; i < numbytes-1; i++) { if (value[i] != 0) { for (int j = 0; j < 8; j++) { bitpos = 7-j; if (((1 << bitpos) & value[i]) != 0) return ((i*8)+j); } } } // only the top part of the last byte is relevant byte mask = (byte)(0xFF << (8-bitsInLastByte)); if ((value[numbytes-1] & mask) != 0) { for (int j = 0; j < bitsInLastByte; j++) { bitpos = 7-j; if (((1 << bitpos) & value[numbytes-1]) != 0) return ((numbytes-1)*8)+j; } } return -1; } /** * Like anySetBit(), but return any set bit whose number is bigger than * beyondBit. If no bit is set after beyondBit, -1 is returned. * By using anySetBit() and anySetBit(beyondBit), one can quickly go * thru the entire bit array to return all set bit. * * @param beyondBit only look at bit that is greater than this bit number * @return the bit number of a bit that is set, or -1 if no bit after * beyondBit is set */ public int anySetBit(int beyondBit) { if (SanityManager.DEBUG) { if (beyondBit >= this.getLength()) SanityManager.THROWASSERT( "Attempt to access bit position that exceeds the max length (" + this.getLength() + ")"); } int startingBit = (beyondBit+1); // we have seen the last bit. if (startingBit >= this.getLength()) return -1; int numbytes = getLengthInBytes(); int startingByte = startingBit / 8; int startingBitpos = startingBit % 8; int bitpos; byte mask; // see if any bits in this byte is set, only the bottom part of the // first byte is relevant mask = (byte)(0xFF >> startingBitpos); if (startingByte == numbytes-1) // starting byte == last byte mask &= (byte)(0xFF << (8-bitsInLastByte)); if ((value[startingByte] & mask ) != 0) { // I know we will see the bit before bitsInLastByte even if we are // at the last byte, no harm in going up to 8 in the loop for (int j = startingBitpos; j < 8; j++) { if (SanityManager.DEBUG) { if (startingByte == numbytes-1) SanityManager.ASSERT(j < bitsInLastByte, "going beyond the last bit"); } bitpos = 7-j; if (((1 << bitpos) & value[startingByte]) != 0) { return (startingByte*8+j); } } } for (int i = (startingByte+1); i < numbytes-1; i++) { if (value[i] != 0) { for (int j = 0; j < 8; j++) { bitpos = 7-j; if (((1 << bitpos) & value[i]) != 0) { return ((i*8)+j); } } } } // Last byte if there are more than one bytes. Only the top part of // the last byte is relevant if (startingByte != numbytes-1) { mask = (byte)(0xFF << (8-bitsInLastByte)); if ((value[numbytes-1] & mask) != 0) { for (int j = 0; j < bitsInLastByte; j++) { bitpos = 7-j; if (((1 << bitpos) & value[numbytes-1]) != 0) { return ((numbytes-1)*8)+j; } } } } return -1; } /** * Bitwise OR this Bit with another Bit. * * @param otherBit the other Bit * @see Bit#or */ public void or(FormatableBitSet otherBit) { if (otherBit == null || otherBit.getLength() == 0) return; int otherLength = otherBit.getLength(); if (otherLength > getLength()) grow(otherLength); // expand this bit if (otherBit instanceof FormatableBitSet) { // we know the bit ordering, optimize this FormatableBitSet ob = (FormatableBitSet)otherBit; int obByteLen = ob.getLengthInBytes(); for (int i = 0; i < obByteLen-1; i++) value[i] |= ob.value[i]; // do the last byte bit by bit for (int i = (obByteLen-1)*8; i < otherLength; i++) if (otherBit.isSet(i)) set(i); } else { // we don't know the bit ordering, call thru the interface and go // thru bit by bit // this bit impl's length >= other bit's length for (int i = 0; i < otherLength; i++) { if (otherBit.isSet(i)) set(i); } } } /** * Bitwise AND this Bit with another Bit. * * @param otherBit the other Bit * @see Bit#or */ public void and(FormatableBitSet otherBit) { if (SanityManager.DEBUG) SanityManager.ASSERT(otherBit != null, "cannot AND null with a FormatableBitSet"); int otherLength = otherBit.getLength(); // Supposedly cannot happen, but handle it just in case. if (otherLength > getLength()) grow(otherLength); // expand this bit if (otherLength < getLength()) { // clear all bits that are not in the other bit int startingByte = (otherLength * 8) + 1; int len = getLengthInBytes(); for (int i = startingByte; i < len; i++) value[i] = 0; for (int i = otherLength; i < startingByte*8; i++) { if (i < getLength()) clear(i); else break; } } if (otherLength == 0) return; int length = otherBit.getLengthInBytes() < getLengthInBytes() ? otherBit.getLengthInBytes() : getLengthInBytes(); for (int i = 0; i < length; i++) value[i] &= otherBit.value[i]; } /** * Logically XORs this FormatableBitSet with the specified FormatableBitSet. * @param set The FormatableBitSet to be XORed with. */ public void xor(FormatableBitSet set) { if (SanityManager.DEBUG) { if (getLength() != set.getLength()) { SanityManager.THROWASSERT("getLength() (" + getLength() + ") and set.getLength() (" + set.getLength() + ") expected to be the same"); } } int setLength = set.getLength(); for (int i = setLength; i-- > 0; ) { if (isSet(i) && set.isSet(i)) { clear(i); } else if (isSet(i) || set.isSet(i)) { set(i); } } } /** * Get a count of the number of bits that are set. * * @return The number of bits that are set. */ public int getNumBitsSet() { int count = 0; for (int index = getLength() - 1; index >= 0; index--) { if (isSet(index)) { count++; } } return count; } ///////////////////////////////////////////////////////// // // EXTERNALIZABLE // ///////////////////////////////////////////////////////// /** * Format: <UL> * <LI>int length in bits </LI> * <LI>byte[] </LI></UL> * * @see java.io.Externalizable#writeExternal */ public void writeExternal(ObjectOutput out) throws IOException { // never called when value is null if (SanityManager.DEBUG) SanityManager.ASSERT(value != null); out.writeInt(getLength()); int byteLen = getLengthInBytes(); if (byteLen > 0) { out.write(value, 0, byteLen); } } /** * Note: gracefully handles zero length * bits -- will create a zero length array * with no bits being used. Fortunately * in.read() is ok with a zero length array * so no special code. * <p> * WARNING: this method cannot be changed w/o * changing SQLBit because SQLBit calls this * directly w/o calling read/writeObject(), so * the format id is not stored in that case. * * @see java.io.Externalizable#readExternal */ public void readExternal(ObjectInput in) throws IOException { int lenInBits; int lenInBytes; lenInBits = in.readInt(); lenInBytes = FormatableBitSet.numBytesFromBits(lenInBits); /* ** How can lenInBytes be zero? The implication is ** that lenInBits is zero. Well, the reason this can ** happen is that the store will reset our stream ** out from underneath us if we are a Bit column that ** overflows onto another page because it assumes that ** we want to stream it in specially. Because of this warped ** API, our readInt() will return 0 even though our ** writeExternal() did a writeInt(xxx). The upshot ** is that you should leave the following alone. */ value = new byte[lenInBytes]; in.readFully(value); bitsInLastByte = numBitsInLastByte(lenInBits); lengthAsBits = lenInBits; } public void readExternalFromArray(ArrayInputStream in) throws IOException { int lenInBits = in.readInt(); int lenInBytes = FormatableBitSet.numBytesFromBits(lenInBits); value = new byte[lenInBytes]; in.readFully(value); bitsInLastByte = numBitsInLastByte(lenInBits); lengthAsBits = lenInBits; } /** * Get the formatID which corresponds to this class. * * @return the formatID of this class */ public int getTypeFormatId() { return StoredFormatIds.BITIMPL_V01_ID; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -