src.com.ibm.as400.util.commtrace.BitBuf Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400 Show documentation
Show all versions of jt400 Show documentation
The Open Source version of the IBM Toolbox for Java
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: BitBuf.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 2002 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.util.commtrace;
import java.io.StringWriter;
/**
* The BitBuf class is an abstraction for an arbitrarily long string of bits.
* Its methods allow bit shifting, substring extraction, converting substrings
* to bytes, shorts, longs, or floats, and representing a bit string as a
* sequence of binary or hexadecimal digits.
* A new BitBuf can be constructed from another BitBuf or from a byte array.
*/
class BitBuf implements Cloneable {
private byte data[];
private int bitlen; // used if not a byte-boundary;
private static StringBuffer binbyte = new StringBuffer("01234567");
private static StringBuffer hexbyte = new StringBuffer("FF");
private final int masks[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
private final char hexchars[] =
{
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
/**
* Constructs a BitBuf from a byte array.
* @param bytes The byte array.
*/
public BitBuf(byte[] bytes) {
data = (byte[]) bytes.clone();
bitlen = data.length * 8;
}
/**
* Constructor for making a BitBuf from an integer array.
* Note that only the lowest 8 bits of each integer are
* used. This is useful for code such as
*
* int ary[] = {0x01, 0xFF, 0x5E};
* BitBuf b = new BitBuf(ary);
*
* which would be bulkier if a byte array were used instead
* because of the need for implicit type casting of each
* element of array.
* @param ints The integer array
*/
public BitBuf(int[] ints) {
data = new byte[ints.length];
for (int i = 0; i < ints.length; i++)
data[i] = (byte) ints[i];
bitlen = data.length * 8;
}
/**
* Constructs an BitBuf of length 8 from a single byte.
* @param b The byte
*/
public BitBuf(byte b) {
data = new byte[1];
data[0] = b;
bitlen = data.length * 8;
}
/**
* Constructs a zero-filled BitBuf of length i*8.
* @param i The length of the BitBuf.
*/
public BitBuf(int i) {
data = new byte[i];
bitlen = data.length * 8;
}
/**
* Constructs a BitBuf from a substring of another BitBuf.
* @param b The BitBuf to copy bytes from.
* @param bitstart The bit to start copying at.
* @param bitlength the number of bits to copy.
*/
public BitBuf(BitBuf b, int bitstart, int bitlength) {
if (bitlength < 0)
bitlength = 0;
bitlen = bitlength;
int newlen = (bitlength + 7) / 8;
data = new byte[newlen];
for (int x = 0; x < newlen; x++)
data[x] = b.getOctet(bitstart + 8 * x);
truncate();
}
/**
* Returns a string of binary digits representing the 8 bits starting at bit i.
* @param i the bit to start the binary string at.
* @return String
*/
public String byteAsBin(int i) {
int x;
for (x = 7; x >= 0; x--)
binbyte.setCharAt(x, ((data[i] & 0xFF & masks[x]) > 0) ? '1' : '0');
return binbyte.toString();
}
/**
* Returns a string of hex digits representing the 8 bits starting at bit i.
* @param i the bit to start the hex string at.
* @return String
*/
public String byteAsHex(int i) {
hexbyte.setCharAt(0, hexchars[data[i] >>> 4 & 0xF]);
hexbyte.setCharAt(1, hexchars[data[i] & 0xF]);
return hexbyte.toString();
}
/**
* Returns a clone of a BitBuf casted as an Object.
* @return Object a clone of this BitBuf.
*/
public Object clone() {
BitBuf b = new BitBuf(data);
return b;
}
/**
* Returns a boolean representing one bit (at offset bit) of the BitBuf.
* @param bit the offset bit to return a boolean of.
* @return true is on, false if off
*/
public boolean getBitAsBool(int bit) {
int byteloc = bit / 8;
int bitloc = bit % 8;
if ((data[byteloc] & 0xFF & masks[bitloc]) > 0)
return true;
else
return false;
}
/**
* Returns a byte representing one bit (at offset bit) of the BitBuf.
* @param bit the offset bit.
* @return the byte at this offset.
*/
public byte getBitAsByte(int bit) {
int byteloc = bit / 8;
int bitloc = bit % 8;
if ((data[byteloc] & 0xFF & masks[bitloc]) > 0)
return (byte) 1;
else
return (byte) 0;
}
/**
* Returns the length of the BitBuf in bits.
* @return Th Length of this BitBuf in bits.
*/
public int getBitSize() {
return bitlen;
}
/**
* Returns a clone of the byte array used to store the data in a BitBuf.
* @return byte[] clone of the data in this BitBuf.
*/
public byte[] getBytes() {
return (byte[]) data.clone();
}
/**
* Returns the length of the BitBuf in bytes. For example, a BitBuf
* with a bit length of 3 would have a byte length of 1.
* @return length of this BitBuf in bytes
*/
public int getByteSize() {
return data.length;
}
/**
* Returns a byte consisting of the 8 bits in the BitBuf starting at startbit.
* @param startbit bit to start the byte at
* @return byte
*/
public byte getOctet(int startbit) {
// Gets 8 bits starting at the bit location bitloc
byte b;
if ((startbit >= bitlen) || (startbit < -8))
b = 0;
else
if (startbit < 0)
b = (byte) ((data[0] & 0xFF) >>> (0 - startbit));
else {
int byteloc = startbit / 8;
int bitshift = startbit % 8;
b = data[byteloc];
b <<= bitshift;
if ((bitshift > 0) && (startbit + 8 < bitlen))
b |= (data[byteloc + 1] & 0xFF) >>> (8 - bitshift);
}
return b;
}
/**
* Shifts the BitBuf left by x bits, shifting zeros in on the right.
* @param x length to shift to the left
*/
public void shiftLeft(int x) {
shiftBufferLeft(x);
}
/**
* Shifts the BitBuf right by x bits, shifting zeros in on the left.
* Slack bits remain zero (meaning that 11101 shifted right by 2 is 00111,
* even though internally the pattern would be stored using 8 bytes)
* @param x length to shift to the right
*/
public void shiftRight(int x) {
shiftBufferRight(x);
truncate();
}
/**
* Efficient left-shifting of entire buffer.
* First, byte-resolution shifting is done in one pass,
* then bit-resolution in one more pass through the buffer.
* @param d length to shift left
*/
public void shiftBufferLeft(int d) {
int byteshift = d / 8;
int bitshift = d % 8;
if (byteshift > 0)
for (int i = 0; i < data.length; i++)
if (i < (data.length - byteshift))
data[i] = data[i + byteshift];
else
data[i] = 0;
if (bitshift > 0)
for (int i = 0; i < data.length; i++)
if (i < (data.length - 1))
data[i] =
(byte) ((data[i] << bitshift) | ((data[i + 1] & 0xFF) >>> (8 - bitshift)));
else
data[i] <<= bitshift;
}
/**
* Efficient right-shifting of entire buffer.
* First, byte-resolution shifting is done in one pass,
* then bit-resolution in one more pass through the buffer.
* @param d length to shift right
*/
public void shiftBufferRight(int d) {
int byteshift = d / 8;
int bitshift = d % 8;
if (byteshift > 0)
for (int i = data.length; i-- > 0;)
if (i >= byteshift)
data[i] = data[i - byteshift];
else
data[i] = 0;
if (bitshift > 0)
for (int i = data.length; i-- > 0;)
if (i > 0)
data[i] =
(byte) (((data[i] & 0xFF) >>> bitshift) | (data[i - 1] << (8 - bitshift)));
else
data[i] = (byte) ((data[i] & 0xFF) >>> bitshift);
}
/**
* Returns a new BitBuf consisting of all bits from offset s and beyond.
* @param s offset at which to slice
* @return The new BitBuf containing the subset of data
*/
public BitBuf slice(int s) {
return new BitBuf(this, s, this.bitlen - s);
}
/**
* Returns a new BitBuf consisting of l bits starting with offset s.
* @param s offset at which to slice
* @param l how may bits to slice
* @return The new BitBuf containing the subset of data
*/
public BitBuf slice(int s, int l) {
return new BitBuf(this, s, l);
}
/**
* Returns a binary string representing the BitBuf, no spacing
* @return String
*/
public String toBinString() {
return toBinString(0, "");
}
/**
* Returns a binary string representing the BitBuf. The separator
* string is inserted into the result after every groupsize bytes.
* @param groupsize
* @param separator
* @return String
*/
public String toBinString(int groupsize, String separator) {
StringWriter out = new StringWriter();
for (int x = 0; x < data.length; x++) {
out.write(byteAsBin(x));
if ((groupsize != 0) && (x % groupsize == 0))
out.write(separator);
}
return out.toString();
}
/**
* Returns a binary string representing the bit buf. Every 8 bits
* is separated by the string sep.
* @param sep
* @return String
*/
public String toBinString(String sep) {
return toBinString(1, sep);
}
/**
* Returns the rightmost 8 bits of the BitBuf as a byte.
* @return byte
*/
public byte toByte() {
return getOctet(bitlen - 8);
}
/**
* Returns a hex string representing the BitBuf, no spacing.
* @return String
*/
public String toHexString() {
return toHexString(0, "");
}
/**
* Returns a hex string representing the BitBuf. The separator
* string is inserted into the result after every groupsize bytes.
* @param groupsize
* @param separator
* @return String
*/
public String toHexString(int groupsize, String separator) {
StringWriter out = new StringWriter();
for (int x = 0; x < data.length; x++) {
if ((x != 0) && (groupsize > 0) && (x % groupsize == 0))
out.write(separator);
out.write(byteAsHex(x));
}
return out.toString();
}
/**
* Returns a hex string representing the bit buf. Every 2 hex digits
* are separated by the string sep.
* @param sep
* @return String
*/
public String toHexString(String sep) {
return toHexString(1, sep);
}
/**
* Works like toHexString(grouplen, separator) except that if the bitlen
* of the BitBuf is not a multiple of 8, the slack bits will be on the left
* instead of the right.
* @param grouplen
* @param separator
* @return String
*/
public String toHexStringJustified(int grouplen, String separator) {
BitBuf b = (BitBuf) this.clone();
int slack = b.bitlen % 8;
if (slack > 0)
b.shiftBufferRight(8 - slack);
return b.toHexString(grouplen, separator);
}
/**
* Returns the rightmost 32 bits of the BitBuf as an int.
* @return int
*/
public int toInt() {
long r = 0;
for (int i = 0; i < 4; i++)
r |= (getOctet(bitlen - 8 * (i + 1)) & 0xFF) << (i * 8);
return (int) r;
}
/**
* Returns the rightmost 64 bits of the BitBuf as a long.
* @return long
*/
public long toLong() {
long r = 0;
for (int i = 0; i < 8; i++)
r |= (long) (getOctet(bitlen - 8 * (i + 1)) & 0xFF) << (i * 8);
return r;
}
/**
* Returns the rightmost 16 bits of the BitBuf as an int.
* @return short
*/
public short toShort() {
long r = 0;
for (int i = 0; i < 2; i++)
r |= (getOctet(bitlen - 8 * (i + 1)) & 0xFF) << (i * 8);
return (short) r;
}
/**
* Set unused bits on right to 0 (for situations like a string bit len of 6, which still takes 1 byte).
*/
private void truncate() {
int tailbits = bitlen % 8;
if (tailbits > 0)
data[data.length - 1] &= ~((1 << (8 - tailbits)) - 1);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy