All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.ibm.as400.util.commtrace.BitBuf Maven / Gradle / Ivy

There is a newer version: 20.0.7
Show newest version
///////////////////////////////////////////////////////////////////////////////
//                                                                             
// 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 - 2024 Weber Informatics LLC | Privacy Policy