/* * `gnu.iou' * Copyright (C) 2006 John Pritchard. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ package gnu.iou ; /** * Bit array encoding: seven bits per byte. * * <p> An enabled high bit marks the use of the following bit values. * The highest bit turned on marks the upper bound of the bit array. * * <p> Each byte is indexed from high to low bits, left to right, * index zero to N. In the first example, below, bit [0] is on, while * in the second and third examples it is off. In the fourth example, * bit [0] is on and bit [1] is off. * * <pre> * 11010101 Seven bits: on, off, on, off, on, off, on. * 01000000 Six bits, off. * 00001010 Three bits, off, on, and off. * 00000110 Two bits, off and on. * 00000011 One bit, on. * 00000000 No bits (invalid). * </pre> * * <p> An array of bits beyond seven bits uses multiple of these * bytes, each employing the identical "high bit" encoding. * * <p> For example, a bit array field of ten bits is two bytes: * <i>11010101,</i> and <i>00001010.</i> The zeroth bit <i>(byte[0] & * 0x40)</i> is on and the nineth bit <i>(byte[1] & 0x1)</i> is off. * * <p><b>Contiguous</b> * * <p> A byte with fewer than seven bit bits is not followed by * another byte in a bit array field, in order that implementations * can quickly calculate the number of bits in an array by counting * the number bytes, and then checking the number of bits in the last * byte. * * @author John Pritchard (john@syntelos.org) */ public class bit { /** * Boolean byte bit mask for the eigth bit (10000000). */ public final static int BOOL_BIT_7 = 0x80; /** * Boolean byte bit mask for the seventh bit (01000000). */ public final static int BOOL_BIT_6 = 0x40; /** * Boolean byte bit mask fir the sixth bit (00100000).*/ public final static int BOOL_BIT_5 = 0x20; /** * Boolean byte bit mask for the fifth bit (00010000). */ public final static int BOOL_BIT_4 = 0x10; /** * Boolean byte bit mask for the fourth bit (00001000). */ public final static int BOOL_BIT_3 = 0x08; /** * Boolean byte bit mask for the third bit (00000100). */ public final static int BOOL_BIT_2 = 0x04; /** * Boolean byte bit mask for the second bit (00000010). */ public final static int BOOL_BIT_1 = 0x02; /** * Boolean byte bit mask for the first bit (00000001). */ public final static int BOOL_BIT_0 = 0x01; /** * Encode boolean array to bit array. * * @param boolary Array of booleans to encode. */ public final static byte[] encode( boolean[] boolary){ if ( null == boolary) return null; byte[] bary; int cc = boolary.length; if ( 7 >= cc){ bary = new byte[1]; bary[0] = (byte)0; bary[0] |= (byte)(1<<cc); for ( int c = 0; c < cc; c++){ if ( boolary[c]) bary[0] |= (byte)(1<<c); } return bary; } else if ( 0 < (cc % 7)) bary = new byte[(cc/7)+1]; else bary = new byte[(cc/7)]; for ( int c = 0, ccc, cccc = 0; c < bary.length; c++){ bary[c] = (byte)0; if ( ((c+1)*7) <= cc){ bary[c] |= BOOL_BIT_7; for ( ccc = 0; ccc < 7; ccc++){ if ( boolary[cccc++]) bary[c] |= (byte)(1<<ccc); } } else { int mod = cc % 7; bary[c] |= (byte)(1<<mod); for ( ccc = 0; ccc < mod; ccc++){ if ( boolary[cccc++]) bary[c] |= (byte)(1<<ccc); } // break (meaning covered by `; c < bary.length;', above) } } return bary; } private final static boolean[] grow_many ( boolean[] src, int many){ if ( 0 >= many) return src; if ( null == src) return new boolean[many]; else { boolean[] copier = new boolean[src.length+many]; System.arraycopy(src,0,copier,0,src.length); return copier; } } /** * Decode bits to array of booleans. * * @param bary Source buffer * * @param ofs Offset in source buffer * * @param len Number of bytes in source buffer */ public final static boolean[] decode( byte[] bary, int ofs, int len){ if ( null == bary) return null; else { boolean boolary[] = null; for ( int c = ofs, cc; c < len; c++){ if ( 1 == (bary[c] & BOOL_BIT_7)){ // seven bits used boolary = grow_many(boolary,7); cc = boolary.length; boolary[cc-6] = (1 == (bary[c] & BOOL_BIT_0)); boolary[cc-5] = (1 == (bary[c] & BOOL_BIT_1)); boolary[cc-4] = (1 == (bary[c] & BOOL_BIT_2)); boolary[cc-3] = (1 == (bary[c] & BOOL_BIT_3)); boolary[cc-2] = (1 == (bary[c] & BOOL_BIT_4)); boolary[cc-1] = (1 == (bary[c] & BOOL_BIT_5)); boolary[cc] = (1 == (bary[c] & BOOL_BIT_6)); } else if ( 1 == (bary[c] & BOOL_BIT_6)){ // six bits used boolary = grow_many(boolary,6); cc = boolary.length; boolary[cc-5] = (1 == (bary[c] & BOOL_BIT_0)); boolary[cc-4] = (1 == (bary[c] & BOOL_BIT_1)); boolary[cc-3] = (1 == (bary[c] & BOOL_BIT_2)); boolary[cc-2] = (1 == (bary[c] & BOOL_BIT_3)); boolary[cc-1] = (1 == (bary[c] & BOOL_BIT_4)); boolary[cc] = (1 == (bary[c] & BOOL_BIT_5)); } else if ( 1 == (bary[c] & BOOL_BIT_5)){ // five bits used boolary = grow_many(boolary,5); cc = boolary.length; boolary[cc-4] = (1 == (bary[c] & BOOL_BIT_0)); boolary[cc-3] = (1 == (bary[c] & BOOL_BIT_1)); boolary[cc-2] = (1 == (bary[c] & BOOL_BIT_2)); boolary[cc-1] = (1 == (bary[c] & BOOL_BIT_3)); boolary[cc] = (1 == (bary[c] & BOOL_BIT_4)); } else if ( 1 == (bary[c] & BOOL_BIT_4)){ // four bits used boolary = grow_many(boolary,4); cc = boolary.length; boolary[cc-3] = (1 == (bary[c] & BOOL_BIT_0)); boolary[cc-2] = (1 == (bary[c] & BOOL_BIT_1)); boolary[cc-1] = (1 == (bary[c] & BOOL_BIT_2)); boolary[cc] = (1 == (bary[c] & BOOL_BIT_3)); } else if ( 1 == (bary[c] & BOOL_BIT_3)){ // three bits used boolary = grow_many(boolary,3); cc = boolary.length-1; boolary[cc-2] = (1 == (bary[c] & BOOL_BIT_0)); boolary[cc-1] = (1 == (bary[c] & BOOL_BIT_1)); boolary[cc] = (1 == (bary[c] & BOOL_BIT_2)); } else if ( 1 == (bary[c] & BOOL_BIT_2)){ // two bits used boolary = grow_many(boolary,2); cc = boolary.length-1; boolary[cc-1] = (1 == (bary[c] & BOOL_BIT_0)); boolary[cc] = (1 == (bary[c] & BOOL_BIT_1)); } else if ( 1 == (bary[c] & BOOL_BIT_1)){ // one bit used boolary = grow_many(boolary,1); boolary[boolary.length-1] = (1 == (bary[c] & BOOL_BIT_0)); } else continue; // no bits used } return boolary; } } }