| CODENOTIFIER | HelpYou are not signed inSign in |
Project: Flanderra
Revision: 19
Author: pcherkas
Date: 09 Aug 2008 17:21:17
Changes:bit logic refactoring and optimization. Initial commit.
Files:| ... | ...@@ -0,0 +1,41 @@ | |
| 1 | package com.flanderra.commons.test.bits; | |
| 2 | ||
| 3 | import com.flanderra.commons.utils.BitInputStream; | |
| 4 | import com.flanderra.commons.utils.BitUtils; | |
| 5 | ||
| 6 | import java.io.ByteArrayInputStream; | |
| 7 | import java.util.BitSet; | |
| 8 | ||
| 9 | import org.apache.commons.logging.Log; | |
| 10 | import org.apache.commons.logging.LogFactory; | |
| 11 | ||
| 12 | import junit.framework.TestCase; | |
| 13 | ||
| 14 | /** | |
| 15 | * @author <a href="mailto:pavlo_cherkashyn@yahoo.com">Pavel Cherkashin</a> | |
| 16 | */ | |
| 17 | public class BitStreamTest extends TestCase { | |
| 18 | private Log log = LogFactory.getLog(BitStreamTest.class); | |
| 19 | ||
| 20 | public void testBitStream() { | |
| 21 | byte[] data = new byte[]{0, 127, -1, -128, -2}; | |
| 22 | String stringularBin1 = BitUtils.bin(data); | |
| 23 | String stringularHex1 = BitUtils.hex(data); | |
| 24 | BitInputStream bis = new BitInputStream(new ByteArrayInputStream(data)); | |
| 25 | BitSet result = bis.readNext(1); | |
| 26 | result = BitUtils.concat(result, bis.readNext(7), 1, 7); | |
| 27 | result = BitUtils.concat(result, bis.readNext(2), 8, 2); | |
| 28 | result = BitUtils.concat(result, bis.readNext(6), 10, 6); | |
| 29 | result = BitUtils.concat(result, bis.readNext(3), 16, 3); | |
| 30 | result = BitUtils.concat(result, bis.readNext(5), 19, 5); | |
| 31 | result = BitUtils.concat(result, bis.readNext(4), 24, 4); | |
| 32 | result = BitUtils.concat(result, bis.readNext(4), 28, 4); | |
| 33 | result = BitUtils.concat(result, bis.readNext(0), 32, 0); | |
| 34 | result = BitUtils.concat(result, bis.readNext(8), 32, 8); | |
| 35 | ||
| 36 | String stringularBin2 = BitUtils.bin(result, 40); | |
| 37 | String stringularHex2 = BitUtils.hex(result, 40); | |
| 38 | assertEquals(stringularBin1, stringularBin2); | |
| 39 | assertEquals(stringularHex1, stringularHex2); | |
| 40 | } | |
| 41 | } |
| ... | ...@@ -0,0 +1,59 @@ | |
| 1 | package com.flanderra.commons.test.bits; | |
| 2 | ||
| 3 | import java.text.DecimalFormat; | |
| 4 | import java.text.MessageFormat; | |
| 5 | import java.text.NumberFormat; | |
| 6 | import java.util.BitSet; | |
| 7 | ||
| 8 | import org.apache.commons.logging.Log; | |
| 9 | import org.apache.commons.logging.LogFactory; | |
| 10 | import org.junit.Assert; | |
| 11 | import org.junit.Ignore; | |
| 12 | import org.junit.Test; | |
| 13 | ||
| 14 | import com.flanderra.commons.utils.BitUtils; | |
| 15 | ||
| 16 | import junit.framework.TestCase; | |
| 17 | ||
| 18 | public class BitUtilsTest { | |
| 19 | private Log log = LogFactory.getLog(BitUtilsTest.class); | |
| 20 | ||
| 21 | @Test | |
| 22 | public void testBinHex() { | |
| 23 | String ptnHex = "00 aa AA 0b 0B"; | |
| 24 | String ptnBin = "00000000 01010101 01010101 00110011 00110011"; | |
| 25 | ||
| 26 | byte[] res1 = BitUtils.hex(ptnHex); | |
| 27 | byte[] res2 = BitUtils._hex(ptnHex); | |
| 28 | ||
| 29 | String reverse1 = BitUtils.hex(res1); | |
| 30 | String reverse2 = BitUtils._hex(res2); | |
| 31 | ||
| 32 | Assert.assertArrayEquals(res1, res2); | |
| 33 | Assert.assertEquals(reverse1, reverse2); | |
| 34 | ||
| 35 | ||
| 36 | } | |
| 37 | ||
| 38 | public String bin(byte[] bytes) { | |
| 39 | StringBuffer sb = new StringBuffer(""); | |
| 40 | for (int i = 0; i < bytes.length; i++) { | |
| 41 | byte val = bytes[i]; | |
| 42 | sb.append(new char[] { (1 & (val >> 7)) == 1 ? '1' : '0', (1 & (val >> 6)) == 1 ? '1' : '0', | |
| 43 | (1 & (val >> 5)) == 1 ? '1' : '0', (1 & (val >> 4)) == 1 ? '1' : '0', (1 & (val >> 3)) == 1 ? '1' : '0', | |
| 44 | (1 & (val >> 2)) == 1 ? '1' : '0', (1 & (val >> 1)) == 1 ? '1' : '0', (1 & (val)) == 1 ? '1' : '0' }); | |
| 45 | sb.append(' '); | |
| 46 | } | |
| 47 | return sb.toString(); | |
| 48 | } | |
| 49 | ||
| 50 | public String bin(byte val) { | |
| 51 | return new String(new char[] { (1 & (val >> 7)) == 1 ? '1' : '0', (1 & (val >> 6)) == 1 ? '1' : '0', | |
| 52 | (1 & (val >> 5)) == 1 ? '1' : '0', (1 & (val >> 4)) == 1 ? '1' : '0', (1 & (val >> 3)) == 1 ? '1' : '0', | |
| 53 | (1 & (val >> 2)) == 1 ? '1' : '0', (1 & (val >> 1)) == 1 ? '1' : '0', (1 & (val)) == 1 ? '1' : '0' }); | |
| 54 | } | |
| 55 | ||
| 56 | public int getBit(byte val, int pos) { | |
| 57 | return (1 & (val >> pos)); | |
| 58 | } | |
| 59 | } |
| ... | ...@@ -13,652 +13,689 @@ | |
| 13 | 13 | * @author <a href="mailto:pavlo_cherkashyn@yahoo.com">Pavel Cherkashin</a> |
| 14 | 14 | */ |
| 15 | 15 | public class BitUtils { |
| 16 | private static Log log = LogFactory.getLog(BitUtils.class); | |
| 16 | private static Log log = LogFactory.getLog(BitUtils.class); | |
| 17 | 17 | |
| 18 | ///////////////////////////////////////////// | |
| 19 | // Constants | |
| 20 | ///////////////////////////////////////////// | |
| 21 | public static final long MIN_UI8 = 0L; | |
| 22 | public static final long MAX_UI8 = 0xFFL; | |
| 23 | public static final long MIN_UI16 = 0L; | |
| 24 | public static final long MAX_UI16 = 0xFFFFL; | |
| 25 | public static final long MIN_UI24 = 0L; | |
| 26 | public static final long MAX_UI24 = 0xFFFFFFL; | |
| 27 | public static final long MIN_UI32 = 0L; | |
| 28 | public static final long MAX_UI32 = 0xFFFFFFFFL; | |
| 29 | public static final long MIN_SI8 = -0x80L; | |
| 30 | public static final long MAX_SI8 = 0x7fL; | |
| 31 | public static final long MIN_SI16 = -0x8000L; | |
| 32 | public static final long MAX_SI16 = 0x7fffL; | |
| 33 | public static final long MIN_SI32 = -0x80000000L; | |
| 34 | public static final long MAX_SI32 = 0x7fffffffL; | |
| 35 | public static final double MIN_FIXED88 = -128.0d; | |
| 36 | public static final double MAX_FIXED88 = 127.99609375d; | |
| 37 | public static final double MIN_FIXED1616 = -32768.0d; | |
| 38 | public static final double MAX_FIXED1616 = 32767.9999847412109375d; | |
| 39 | public static final double MIN_FLOAT16 = 0x0.1P-14d; | |
| 40 | public static final double MAX_FLOAT16 = 0x3.FEP15d; | |
| 41 | public static final double MIN_FLOAT32 = Float.MIN_VALUE; | |
| 42 | public static final double MAX_FLOAT32 = Float.MAX_VALUE; | |
| 43 | public static final double MIN_FLOAT64 = Double.MIN_VALUE; | |
| 44 | public static final double MAX_FLOAT64 = Double.MAX_VALUE; | |
| 45 | private static final char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | |
| 46 | ||
| 47 | ///////////////////////////////////////////// | |
| 48 | // utility methods for basic types | |
| 49 | ///////////////////////////////////////////// | |
| 50 | public static BitSet bitsUI8(long val) { | |
| 51 | Assert.inRange(val, MIN_UI8, MAX_UI8); | |
| 52 | BitSet bitset = longToBits(val, 8); | |
| 53 | return bitset; | |
| 54 | } | |
| 55 | ||
| 56 | public static byte[] bytesUI8(long val) { | |
| 57 | return bitsToBytes(bitsUI8(val), 8); | |
| 58 | } | |
| 59 | ||
| 60 | public static long parseUI8(byte[] val) { | |
| 61 | return bytesToLong(new byte[]{val[0]}, false); | |
| 62 | } | |
| 63 | ||
| 64 | public static BitSet bitsUI16(long val) { | |
| 65 | Assert.inRange(val, MIN_UI16, MAX_UI16); | |
| 66 | return flipBytes(longToBits(val, 16), 2); | |
| 67 | } | |
| 68 | ||
| 69 | public static byte[] bytesUI16(long val) { | |
| 70 | return bitsToBytes(bitsUI16(val), 16); | |
| 71 | } | |
| 72 | ||
| 73 | public static long parseUI16(byte[] val) { | |
| 74 | return bytesToLong(new byte[]{val[0], val[1]}, false); | |
| 75 | } | |
| 76 | ||
| 77 | public static BitSet bitsUI24(long val) { | |
| 78 | Assert.inRange(val, MIN_UI24, MAX_UI24); | |
| 79 | return flipBytes(longToBits(val, 24), 3); | |
| 80 | } | |
| 81 | ||
| 82 | public static byte[] bytesUI24(long val) { | |
| 83 | return bitsToBytes(bitsUI24(val), 24); | |
| 84 | } | |
| 85 | ||
| 86 | public static long parseUI24(byte[] val) { | |
| 87 | return bytesToLong(new byte[]{val[0], val[1], val[2]}, false); | |
| 88 | } | |
| 89 | ||
| 90 | public static BitSet bitsUI32(long val) { | |
| 91 | Assert.inRange(val, MIN_UI32, MAX_UI32); | |
| 92 | return flipBytes(longToBits(val, 32), 4); | |
| 93 | } | |
| 94 | ||
| 95 | public static byte[] bytesUI32(long val) { | |
| 96 | return bitsToBytes(bitsUI32(val), 32); | |
| 97 | } | |
| 98 | ||
| 99 | public static long parseUI32(byte[] val) { | |
| 100 | return bytesToLong(new byte[]{val[0], val[1], val[2], val[3]}, false); | |
| 101 | } | |
| 102 | ||
| 103 | public static BitSet bitsSI8(long val) { | |
| 104 | Assert.inRange(val, MIN_SI8, MAX_SI8); | |
| 105 | return longToBits(val, 8); | |
| 106 | } | |
| 107 | ||
| 108 | public static byte[] bytesSI8(long val) { | |
| 109 | return bitsToBytes(bitsSI8(val), 8); | |
| 110 | } | |
| 111 | ||
| 112 | public static long parseSI8(byte[] val) { | |
| 113 | return bytesToLong(new byte[]{val[0]}, true); | |
| 114 | } | |
| 115 | ||
| 116 | public static BitSet bitsSI16(long val) { | |
| 117 | Assert.inRange(val, MIN_SI16, MAX_SI16); | |
| 118 | return flipBytes(longToBits(val, 16), 2); | |
| 119 | } | |
| 120 | ||
| 121 | public static byte[] bytesSI16(long val) { | |
| 122 | return bitsToBytes(bitsSI16(val), 16); | |
| 123 | } | |
| 124 | ||
| 125 | public static long parseSI16(byte[] val) { | |
| 126 | return bytesToLong(new byte[]{val[0], val[1]}, true); | |
| 127 | } | |
| 128 | ||
| 129 | public static BitSet bitsSI32(long val) { | |
| 130 | Assert.inRange(val, MIN_SI32, MAX_SI32); | |
| 131 | return flipBytes(longToBits(val, 32), 4); | |
| 132 | } | |
| 133 | ||
| 134 | public static byte[] bytesSI32(long val) { | |
| 135 | return bitsToBytes(bitsSI32(val), 32); | |
| 136 | } | |
| 137 | ||
| 138 | public static byte[] bytesSTRING(String val) { | |
| 139 | try { | |
| 140 | if (val == null || val.equals("")) { | |
| 141 | return new byte[]{0x00}; | |
| 142 | } | |
| 143 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
| 144 | baos.write(val.getBytes("UTF-8")); | |
| 145 | baos.write(0x00); | |
| 146 | return baos.toByteArray(); | |
| 147 | } catch (IOException e) { | |
| 148 | log.error(e); | |
| 149 | throw new RuntimeException(e); | |
| 150 | } | |
| 151 | } | |
| 152 | ||
| 153 | public static long parseSI32(byte[] val) { | |
| 154 | return bytesToLong(new byte[]{val[0], val[1], val[2], val[3]}, true); | |
| 155 | } | |
| 156 | ||
| 157 | public static BitSet bitsFixed88(double val) { | |
| 158 | Assert.inRange(val, MIN_FIXED88, MAX_FIXED88); | |
| 159 | return bitsSI16((short) (val * 256.0)); | |
| 160 | } | |
| 161 | ||
| 162 | public static byte[] bytesFixed88(double val) { | |
| 163 | return bitsToBytes(bitsFixed88(val), 16); | |
| 164 | } | |
| 165 | ||
| 166 | public static double parseFixed88(byte[] val) { | |
| 167 | return ((double) parseSI16(val)) / 256.0; | |
| 168 | } | |
| 169 | ||
| 170 | public static BitSet bitsFixed1616(double val) { | |
| 171 | Assert.inRange(val, MIN_FIXED1616, MAX_FIXED1616); | |
| 172 | BitSet result = new BitSet(32); | |
| 173 | result = concat(result, bitsSI32((int) (val * 65536.0)), 0, 32); | |
| 174 | return result; | |
| 175 | } | |
| 176 | ||
| 177 | public static byte[] bytesFixed1616(double val) { | |
| 178 | return bitsToBytes(bitsFixed1616(val), 32); | |
| 179 | } | |
| 180 | ||
| 181 | public static double parseFixed1616(byte[] val) { | |
| 182 | return ((double) parseSI32(val)) / 65536.0; | |
| 183 | } | |
| 184 | ||
| 185 | public static BitSet bitsFloat16(double val) { | |
| 186 | Assert.inRange(val, MIN_FLOAT16, MAX_FLOAT16); | |
| 187 | int bits32 = Float.floatToIntBits((float) val); | |
| 188 | int sign = Math.abs((bits32 & 0x80000000) >> 31); | |
| 189 | int exponent32 = (bits32 & 0x7f800000) >> 23; | |
| 190 | int mantissa32 = bits32 & 0x7fffff; | |
| 191 | int exponent16 = 0; | |
| 192 | if (exponent32 != 0) { | |
| 193 | if (exponent32 == 0xff) { | |
| 194 | exponent16 = 0x1f; | |
| 195 | } else { | |
| 196 | exponent16 = exponent32 - 127 + 15; | |
| 197 | } | |
| 198 | } | |
| 199 | int mantissa16 = 0; | |
| 200 | if (exponent16 < 0) { | |
| 201 | exponent16 = 0; //positive/negative zero | |
| 202 | } else if (exponent16 > 0x1f) { | |
| 203 | exponent16 = 0x1f; // infinity | |
| 204 | } else { | |
| 205 | mantissa16 = mantissa32 >> 13; | |
| 206 | } | |
| 207 | int bits16 = sign << 15; | |
| 208 | bits16 |= exponent16 << 10; | |
| 209 | bits16 |= mantissa16; | |
| 210 | return bitsUI16(bits16); | |
| 211 | } | |
| 212 | ||
| 213 | public static byte[] bytesFloat16(double val) { | |
| 214 | return bitsToBytes(bitsFloat16(val), 16); | |
| 215 | } | |
| 216 | ||
| 217 | public static double parseFloat16(byte[] val) { | |
| 218 | BitSet bits16 = bytesToBits(val); | |
| 219 | bits16 = flipBytes(bits16, 2); | |
| 220 | BitSet bits32 = new BitSet(); | |
| 221 | boolean sign = false; | |
| 222 | int exponent16 = 0; | |
| 223 | int exponent32 = 0; | |
| 224 | long mantissa16 = 0; | |
| 225 | long mantissa32 = 0; | |
| 226 | int intbits32 = 0; | |
| 227 | float result; | |
| 228 | sign = bits16.get(0); | |
| 229 | for (int i = 1; i < 6; i++) { | |
| 230 | exponent16 |= ((long) (bits16.get(i) ? 1 : 0) << (6 - i - 1)); | |
| 231 | } | |
| 232 | ||
| 233 | for (int i = 6; i < 16; i++) { | |
| 234 | mantissa16 |= ((long) (bits16.get(i) ? 1 : 0) << (16 - i - 1)); | |
| 235 | } | |
| 236 | ||
| 237 | exponent32 = exponent16 + 127 - 15; | |
| 238 | mantissa32 = mantissa16 << 13; | |
| 239 | bits32.set(0, sign); | |
| 240 | // bits32 = concat(bits32, bitsUBArray(exponent32, 8), 1, 8); | |
| 241 | // bits32 = concat(bits32, bitsUBArray(mantissa32, 23), 9, 23); | |
| 242 | // intbits32 = (int) bitsToLong(bits32, 32, true); | |
| 243 | intbits32 |= sign ? 1 : 0 << 31; | |
| 244 | intbits32 |= exponent32 << 23; | |
| 245 | intbits32 |= mantissa32; | |
| 246 | result = Float.intBitsToFloat(intbits32); | |
| 247 | return result; | |
| 248 | } | |
| 249 | ||
| 250 | public static BitSet bitsFloat32(double val) { | |
| 251 | Assert.inRange(val, MIN_FLOAT32, MAX_FLOAT32); | |
| 252 | return bitsSI32(Float.floatToIntBits((float) val)); | |
| 253 | } | |
| 254 | ||
| 255 | public static double parseFloat32(byte[] val) { | |
| 256 | return Float.intBitsToFloat((int) parseSI32(val)); | |
| 257 | } | |
| 258 | ||
| 259 | public static byte[] bytesFloat32(double val) { | |
| 260 | return bitsToBytes(bitsFloat32(val), 32); | |
| 261 | } | |
| 262 | ||
| 263 | public static BitSet bitsFloat64(double val) { | |
| 264 | Assert.inRange(val, MIN_FLOAT64, MAX_FLOAT64); | |
| 265 | BitSet result; | |
| 266 | long longBits = Double.doubleToLongBits(val); | |
| 267 | long byte0 = (byte) (longBits >> 32); | |
| 268 | long byte1 = (byte) (longBits >> 40); | |
| 269 | long byte2 = (byte) (longBits >> 48); | |
| 270 | long byte3 = (byte) (longBits >> 56); | |
| 271 | long byte4 = (byte) (longBits); | |
| 272 | long byte5 = (byte) (longBits >> 8); | |
| 273 | long byte6 = (byte) (longBits >> 16); | |
| 274 | long byte7 = (byte) (longBits >> 24); | |
| 275 | result = bitsSI8(byte0); | |
| 276 | result = concat(result, bitsSI8(byte1), 8, 8); | |
| 277 | result = concat(result, bitsSI8(byte2), 16, 8); | |
| 278 | result = concat(result, bitsSI8(byte3), 24, 8); | |
| 279 | result = concat(result, bitsSI8(byte4), 32, 8); | |
| 280 | result = concat(result, bitsSI8(byte5), 40, 8); | |
| 281 | result = concat(result, bitsSI8(byte6), 48, 8); | |
| 282 | result = concat(result, bitsSI8(byte7), 56, 8); | |
| 283 | return result; | |
| 284 | } | |
| 285 | ||
| 286 | public static byte[] bytesFloat64(double val) { | |
| 287 | return bitsToBytes(bitsFloat64(val), 64); | |
| 288 | } | |
| 289 | ||
| 290 | public static double parseFloat64(byte[] val) { | |
| 291 | BitSet result = bytesToBits(new byte[]{val[3], val[2], val[1], val[0], val[7], val[6], val[5], val[4]}); | |
| 292 | return Double.longBitsToDouble(bitsToLong(result, 64, true)); | |
| 293 | } | |
| 294 | ||
| 295 | public static BitSet bitsFBArray(double val, int bitNumber) { | |
| 296 | Assert.inRange(val, bitNumber); | |
| 297 | BitSet rawResult = bitsFixed1616(val); | |
| 298 | rawResult = flipBytes(rawResult, 4); | |
| 299 | BitSet result = new BitSet(); | |
| 300 | result.set(0, rawResult.get(0)); | |
| 301 | for (int i = 1; i < bitNumber; i++) { | |
| 302 | result.set(i, rawResult.get(i + (32 - bitNumber))); | |
| 303 | } | |
| 304 | return result; | |
| 305 | } | |
| 306 | ||
| 307 | public static byte[] bytesFBArray(double val, int bitNumber) { | |
| 308 | return bitsToBytes(bitsFBArray(val, bitNumber), bitNumber); | |
| 309 | } | |
| 310 | ||
| 311 | public static double parseFBArray(BitSet val, int bitNumber) { | |
| 312 | double result = 0l; | |
| 313 | if (bitNumber < 32) { | |
| 314 | BitSet bits = concat(new BitSet(), val, 32 - bitNumber, 32); | |
| 315 | result = parseFixed1616(bitsToBytes(flipBytes(bits, 4), 32)); | |
| 316 | } else if (bitNumber > 32) { | |
| 317 | BitSet bits = sub(val, 0, 32); | |
| 318 | result = parseFixed1616(bitsToBytes(flipBytes(bits, 4), 32)); | |
| 319 | } else { | |
| 320 | result = parseFixed1616(bitsToBytes(flipBytes(val, 4), 32)); | |
| 321 | } | |
| 322 | return result; | |
| 323 | } | |
| 324 | ||
| 325 | public static BitSet bitsSBArray(long val, int bits) { | |
| 326 | Assert.inRange(val, bits, true); | |
| 327 | return longToBits(val, bits); | |
| 328 | } | |
| 329 | ||
| 330 | ||
| 331 | public static byte[] bytesSBArray(long val, int bits) { | |
| 332 | return bitsToBytes(bitsSBArray(val, bits), bits); | |
| 333 | } | |
| 334 | ||
| 335 | public static long parseSBArray(BitSet val, int bits) { | |
| 336 | return bitsToLong(val, bits, true); | |
| 337 | } | |
| 338 | ||
| 339 | public static long parseSBArray(byte[] val) { | |
| 340 | return bytesToLong(val, true); | |
| 341 | } | |
| 342 | ||
| 343 | public static BitSet bitsUBArray(long val, int bits) { | |
| 344 | Assert.inRange(val, bits, false); | |
| 345 | return longToBits(val, bits); | |
| 346 | } | |
| 347 | ||
| 348 | public static byte[] bytesUBArray(long val, int bits) { | |
| 349 | return bitsToBytes(bitsUBArray(val, bits), bits); | |
| 350 | } | |
| 351 | ||
| 352 | public static long parseUBArray(BitSet val, int bits) { | |
| 353 | return bitsToLong(val, bits, false); | |
| 354 | } | |
| 355 | ||
| 356 | public static long parseUBArray(byte[] val) { | |
| 357 | return bytesToLong(val, false); | |
| 358 | } | |
| 359 | ||
| 360 | public static BitSet bitsEncodedU32(byte[] pos) { | |
| 361 | if (pos.length > 5) { | |
| 362 | throw new RuntimeException("trying to encode more then 5 bytes"); | |
| 363 | } | |
| 364 | long result = pos[0]; | |
| 365 | if ((result & 0x00000080) != 0) { | |
| 366 | return bitsUI32(result); | |
| 367 | } | |
| 368 | result = (result & 0x0000007f) | pos[1] << 7; | |
| 369 | if ((result & 0x00004000) != 0) { | |
| 370 | return bitsUI32(result); | |
| 371 | } | |
| 372 | result = (result & 0x00003fff) | pos[2] << 14; | |
| 373 | if ((result & 0x00200000) != 0) { | |
| 374 | return bitsUI32(result); | |
| 375 | } | |
| 376 | result = (result & 0x001fffff) | pos[3] << 21; | |
| 377 | if ((result & 0x10000000) != 0) { | |
| 378 | return bitsUI32(result); | |
| 379 | } | |
| 380 | result = (result & 0x0fffffff) | pos[4] << 28; | |
| 381 | return bitsUI32(result); | |
| 382 | } | |
| 383 | ||
| 384 | public static byte[] bytesEncodedU32(byte[] pos) { | |
| 385 | return bitsToBytes(bitsEncodedU32(pos), 32); | |
| 386 | } | |
| 387 | ||
| 388 | ///////////////////////////////////////////// | |
| 389 | // Resusable utility methods | |
| 390 | ///////////////////////////////////////////// | |
| 391 | private static BitSet longToBits(long val, int size) { | |
| 392 | String bits = Long.toBinaryString(val); | |
| 393 | if (bits.length() > size) { | |
| 394 | bits = bits.substring(bits.length() - size); | |
| 395 | } | |
| 396 | BitSet bitset = new BitSet(size); | |
| 397 | if (bits != null && bits.length() > 0) { | |
| 398 | int shift = size - bits.length(); | |
| 399 | if (shift < 0) { | |
| 400 | throw new RuntimeException("type is larger then expected"); | |
| 401 | } | |
| 402 | for (int i = 0; i < bits.length(); i++) { | |
| 403 | bitset.set(shift + i, (bits.charAt(i) == '1')); | |
| 404 | } | |
| 405 | } | |
| 406 | return bitset; | |
| 407 | } | |
| 408 | ||
| 409 | private static long bitsToLong(BitSet bitSet, int numBits, boolean signed) { | |
| 410 | long result = 0l; | |
| 411 | if (!signed) { | |
| 412 | for (int i = 0; i < numBits; i++) { | |
| 413 | result |= ((long) (bitSet.get(i) ? 1 : 0) << (numBits - i - 1)); | |
| 414 | } | |
| 415 | } else { | |
| 416 | for (int i = 1; i < numBits; i++) { | |
| 417 | result |= ((long) (bitSet.get(i) ? 1 : 0) << (numBits - i - 1)); | |
| 418 | } | |
| 419 | if (bitSet.get(0)) { | |
| 420 | result -= Math.pow(2, numBits) / 2; | |
| 421 | } | |
| 422 | } | |
| 423 | return result; | |
| 424 | } | |
| 425 | ||
| 426 | private static long bitsToLong(BitSet bitSet, int startPosition, int numBits, boolean signed) { | |
| 427 | long result = 0l; | |
| 428 | if (!signed) { | |
| 429 | for (int i = startPosition; i < (startPosition + numBits); i++) { | |
| 430 | result |= ((long) (bitSet.get(i) ? 1 : 0) << ((startPosition + numBits) - i - 1)); | |
| 431 | } | |
| 432 | } else { | |
| 433 | for (int i = startPosition + 1; i < (startPosition + numBits); i++) { | |
| 434 | result |= ((long) (bitSet.get(i) ? 1 : 0) << ((startPosition + numBits) - i - 1)); | |
| 435 | } | |
| 436 | if (bitSet.get(startPosition)) { | |
| 437 | result -= Math.pow(2, numBits) / 2; | |
| 438 | } | |
| 439 | } | |
| 440 | return result; | |
| 441 | } | |
| 442 | ||
| 443 | private static long bytesToLong(byte[] val, boolean signed) { | |
| 444 | long result = 0l; | |
| 445 | BitSet bitSet = bytesToBits(val); | |
| 446 | bitSet = flipBytes(bitSet, val.length); | |
| 447 | if (!signed) { | |
| 448 | for (int i = 0; i < val.length * 8; i++) { | |
| 449 | result |= ((long) (bitSet.get(i) ? 1 : 0) << (val.length * 8 - i - 1)); | |
| 450 | } | |
| 451 | } else { | |
| 452 | for (int i = 1; i < val.length * 8; i++) { | |
| 453 | result |= ((long) (bitSet.get(i) ? 1 : 0) << (val.length * 8 - i - 1)); | |
| 454 | } | |
| 455 | if (bitSet.get(0)) { | |
| 456 | result -= Math.pow(2, val.length * 8) / 2; | |
| 457 | } | |
| 458 | ||
| 459 | } | |
| 460 | return result; | |
| 461 | } | |
| 462 | ||
| 463 | public static int calculateMaxBitCountUI(long[] data) { | |
| 464 | Arrays.sort(data); | |
| 465 | if (data[data.length - 1] == 0) { | |
| 466 | return 0; | |
| 467 | } else { | |
| 468 | return 32 - BitUtils.bitsToString( | |
| 469 | BitUtils.flipBytes( | |
| 470 | BitUtils.bitsUI32(data[data.length - 1]), | |
| 471 | 4), | |
| 472 | 32).indexOf('1') + 0; | |
| 473 | } | |
| 474 | } | |
| 475 | ||
| 476 | public static int calculateMaxBitCountSI(long[] data) { | |
| 477 | for (int i = 0; i < data.length; i++) { | |
| 478 | if (data[i] < 0) { | |
| 479 | data[i] *= -1; | |
| 480 | } | |
| 481 | } | |
| 482 | Arrays.sort(data); | |
| 483 | if (data[data.length - 1] == 0) { | |
| 484 | return 0; | |
| 485 | } else { | |
| 486 | return 32 - BitUtils.bitsToString( | |
| 487 | BitUtils.flipBytes( | |
| 488 | BitUtils.bitsUI32(data[data.length - 1]), | |
| 489 | 4), | |
| 490 | 32).indexOf('1') + 1; | |
| 491 | } | |
| 492 | ||
| 493 | } | |
| 494 | ||
| 495 | public static int calculateMaxBitCount(double[] data) { | |
| 496 | Arrays.sort(data); | |
| 497 | if (data[data.length - 1] == 0.0) { | |
| 498 | return 16; | |
| 499 | } else { | |
| 500 | int result = 32 - BitUtils.bitsToString(BitUtils.flipBytes(BitUtils.bitsFixed1616(data[data.length - 1]), 4), 32).indexOf('1') + 1; | |
| 501 | return (result > 15) ? result : 16; | |
| 502 | } | |
| 503 | } | |
| 504 | ||
| 505 | public static BitSet stringToBits(String bits, int length) { | |
| 506 | BitSet bitset = new BitSet(length); | |
| 507 | if (bits != null && bits.length() > 0) { | |
| 508 | int shift = length - bits.length(); | |
| 509 | if (shift < 0) { | |
| 510 | throw new RuntimeException("type is larger then expected"); | |
| 511 | } | |
| 512 | for (int i = 0; i < bits.length(); i++) { | |
| 513 | bitset.set(shift + i, (bits.charAt(i) == '1')); | |
| 514 | } | |
| 515 | } | |
| 516 | return bitset; | |
| 517 | } | |
| 518 | ||
| 519 | public static String bitsToString(BitSet bitSet, int bitNumber) { | |
| 520 | StringBuffer sb = new StringBuffer(""); | |
| 521 | for (int i = 0; i < bitNumber; i++) { | |
| 522 | sb.append((bitSet.get(i)) ? '1' : '0'); | |
| 523 | } | |
| 524 | return sb.toString(); | |
| 525 | } | |
| 526 | ||
| 527 | public static byte[] bitsToBytes(BitSet bitSet, int bitNumber) { | |
| 528 | StringBuffer sb = new StringBuffer(""); | |
| 529 | int byteNumber = ((bitNumber % 8) == 0) ? | |
| 530 | (bitNumber / 8) : | |
| 531 | (bitNumber / 8 + 1); | |
| 532 | byte[] result = new byte[byteNumber]; | |
| 533 | for (int i = 0; i < byteNumber; i++) { | |
| 534 | int bin1 = (bitSet.get(i * 8)) ? 128 : 0; | |
| 535 | bin1 += (bitSet.get(i * 8 + 1)) ? 64 : 0; | |
| 536 | bin1 += (bitSet.get(i * 8 + 2)) ? 32 : 0; | |
| 537 | bin1 += (bitSet.get(i * 8 + 3)) ? 16 : 0; | |
| 538 | ||
| 539 | bin1 += (bitSet.get(i * 8 + 4)) ? 8 : 0; | |
| 540 | bin1 += (bitSet.get(i * 8 + 5)) ? 4 : 0; | |
| 541 | bin1 += (bitSet.get(i * 8 + 6)) ? 2 : 0; | |
| 542 | bin1 += (bitSet.get(i * 8 + 7)) ? 1 : 0; | |
| 543 | result[i] = (byte) bin1; | |
| 544 | } | |
| 545 | return result; | |
| 546 | } | |
| 547 | ||
| 548 | public static BitSet bytesToBits(byte[] val) { | |
| 549 | BitSet result = new BitSet(); | |
| 550 | for (int i = 0; i < val.length; i++) { | |
| 551 | byte b = val[i]; | |
| 552 | result = concat(result, bitsSI8(b), i * 8, 8); | |
| 553 | } | |
| 554 | return result; | |
| 555 | } | |
| 556 | ||
| 557 | public static BitSet concat(BitSet bs1, BitSet bs2, int size1, int size2) { | |
| 558 | BitSet result = new BitSet(); | |
| 559 | for (int i = 0; i < size1; i++) { | |
| 560 | result.set(i, bs1.get(i)); | |
| 561 | } | |
| 562 | for (int i = 0; i < size2; i++) { | |
| 563 | result.set(i + size1, bs2.get(i)); | |
| 564 | } | |
| 565 | return result; | |
| 566 | } | |
| 567 | ||
| 568 | public static BitSet sub(BitSet val, int start, int end) { | |
| 569 | BitSet result = new BitSet(); | |
| 570 | for (int i = start; i <= end; i++) { | |
| 571 | result.set(i - start, val.get(i)); | |
| 572 | } | |
| 573 | return result; | |
| 574 | } | |
| 575 | ||
| 576 | public static BitSet flipBytes(BitSet val, int byteNumber) { | |
| 577 | BitSet result = new BitSet(); | |
| 578 | for (int i = 0; i < byteNumber; i++) { | |
| 579 | for (int j = 0; j < 8; j++) { | |
| 580 | result.set(8 * i + j, val.get(8 * (byteNumber - 1 - i) + j)); | |
| 581 | } | |
| 582 | } | |
| 583 | return result; | |
| 584 | } | |
| 585 | ||
| 586 | public static int toTweeps(double val) { | |
| 587 | return (int) Math.ceil(val * 20); | |
| 588 | } | |
| 589 | ||
| 590 | ///////////////////////////////////////////// | |
| 591 | // Resusable formatting methods | |
| 592 | ///////////////////////////////////////////// | |
| 593 | public static String bin(BitSet bitSet, int bitNumber) { | |
| 594 | StringBuffer sb = new StringBuffer(""); | |
| 595 | for (int i = 0; i < bitNumber; i++) { | |
| 596 | if (((i % 8) == 0) && (i != 0)) { | |
| 597 | sb.append(' '); | |
| 598 | } | |
| 599 | sb.append((bitSet.get(i)) ? '1' : '0'); | |
| 600 | } | |
| 601 | return sb.toString(); | |
| 602 | } | |
| 603 | ||
| 604 | public static String bin(byte[] data) { | |
| 605 | return bin(bytesToBits(data), 8 * data.length); | |
| 606 | } | |
| 607 | ||
| 608 | public static String hex(BitSet bitSet, int bitNumber) { | |
| 609 | StringBuffer sb = new StringBuffer(""); | |
| 610 | int byteNumber = ((bitNumber % 8) == 0) ? | |
| 611 | (bitNumber / 8) : | |
| 612 | (bitNumber / 8 + 1); | |
| 613 | for (int i = 0; i < byteNumber; i++) { | |
| 614 | int bin1 = (bitSet.get(i * 8)) ? 8 : 0; | |
| 615 | bin1 += (bitSet.get(i * 8 + 1)) ? 4 : 0; | |
| 616 | bin1 += (bitSet.get(i * 8 + 2)) ? 2 : 0; | |
| 617 | bin1 += (bitSet.get(i * 8 + 3)) ? 1 : 0; | |
| 618 | ||
| 619 | int bin2 = (bitSet.get(i * 8 + 4)) ? 8 : 0; | |
| 620 | bin2 += (bitSet.get(i * 8 + 5)) ? 4 : 0; | |
| 621 | bin2 += (bitSet.get(i * 8 + 6)) ? 2 : 0; | |
| 622 | bin2 += (bitSet.get(i * 8 + 7)) ? 1 : 0; | |
| 623 | sb.append(hexChars[bin1]); | |
| 624 | sb.append(hexChars[bin2]); | |
| 625 | sb.append(' '); | |
| 626 | } | |
| 627 | return sb.toString(); | |
| 628 | } | |
| 629 | ||
| 630 | public static String hex(byte[] data) { | |
| 631 | int byteNumber = data.length; | |
| 632 | StringBuffer sb = new StringBuffer(""); | |
| 633 | for (int i = 0; i < byteNumber; i++) { | |
| 634 | BitSet bitSet = bitsSI8(data[i]); | |
| 635 | int bin1 = (bitSet.get(0)) ? 8 : 0; | |
| 636 | bin1 += (bitSet.get(1)) ? 4 : 0; | |
| 637 | bin1 += (bitSet.get(2)) ? 2 : 0; | |
| 638 | bin1 += (bitSet.get(3)) ? 1 : 0; | |
| 639 | ||
| 640 | int bin2 = (bitSet.get(4)) ? 8 : 0; | |
| 641 | bin2 += (bitSet.get(5)) ? 4 : 0; | |
| 642 | bin2 += (bitSet.get(6)) ? 2 : 0; | |
| 643 | bin2 += (bitSet.get(7)) ? 1 : 0; | |
| 644 | sb.append(hexChars[bin1]); | |
| 645 | sb.append(hexChars[bin2]); | |
| 646 | sb.append(' '); | |
| 647 | } | |
| 648 | return sb.toString(); | |
| 649 | } | |
| 650 | ||
| 651 | public static byte[] hex(String data){ | |
| 652 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
| 653 | String[] strBytes = data.split(" "); | |
| 654 | for (int i = 0; i < strBytes.length; i++) { | |
| 18 | // /////////////////////////////////////////// | |
| 19 | // Constants | |
| 20 | // /////////////////////////////////////////// | |
| 21 | public static final long MIN_UI8 = 0L; | |
| 22 | public static final long MAX_UI8 = 0xFFL; | |
| 23 | public static final long MIN_UI16 = 0L; | |
| 24 | public static final long MAX_UI16 = 0xFFFFL; | |
| 25 | public static final long MIN_UI24 = 0L; | |
| 26 | public static final long MAX_UI24 = 0xFFFFFFL; | |
| 27 | public static final long MIN_UI32 = 0L; | |
| 28 | public static final long MAX_UI32 = 0xFFFFFFFFL; | |
| 29 | public static final long MIN_SI8 = -0x80L; | |
| 30 | public static final long MAX_SI8 = 0x7fL; | |
| 31 | public static final long MIN_SI16 = -0x8000L; | |
| 32 | public static final long MAX_SI16 = 0x7fffL; | |
| 33 | public static final long MIN_SI32 = -0x80000000L; | |
| 34 | public static final long MAX_SI32 = 0x7fffffffL; | |
| 35 | public static final double MIN_FIXED88 = -128.0d; | |
| 36 | public static final double MAX_FIXED88 = 127.99609375d; | |
| 37 | public static final double MIN_FIXED1616 = -32768.0d; | |
| 38 | public static final double MAX_FIXED1616 = 32767.9999847412109375d; | |
| 39 | public static final double MIN_FLOAT16 = 0x0.1P-14d; | |
| 40 | public static final double MAX_FLOAT16 = 0x3.FEP15d; | |
| 41 | public static final double MIN_FLOAT32 = Float.MIN_VALUE; | |
| 42 | public static final double MAX_FLOAT32 = Float.MAX_VALUE; | |
| 43 | public static final double MIN_FLOAT64 = Double.MIN_VALUE; | |
| 44 | public static final double MAX_FLOAT64 = Double.MAX_VALUE; | |
| 45 | private static final char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; | |
| 46 | ||
| 47 | // /////////////////////////////////////////// | |
| 48 | // utility methods for basic types | |
| 49 | // /////////////////////////////////////////// | |
| 50 | public static BitSet bitsUI8(long val) { | |
| 51 | Assert.inRange(val, MIN_UI8, MAX_UI8); | |
| 52 | BitSet bitset = longToBits(val, 8); | |
| 53 | return bitset; | |
| 54 | } | |
| 55 | ||
| 56 | public static byte[] bytesUI8(long val) { | |
| 57 | return bitsToBytes(bitsUI8(val), 8); | |
| 58 | } | |
| 59 | ||
| 60 | public static long parseUI8(byte[] val) { | |
| 61 | return bytesToLong(new byte[] { val[0] }, false); | |
| 62 | } | |
| 63 | ||
| 64 | public static BitSet bitsUI16(long val) { | |
| 65 | Assert.inRange(val, MIN_UI16, MAX_UI16); | |
| 66 | return flipBytes(longToBits(val, 16), 2); | |
| 67 | } | |
| 68 | ||
| 69 | public static byte[] bytesUI16(long val) { | |
| 70 | return bitsToBytes(bitsUI16(val), 16); | |
| 71 | } | |
| 72 | ||
| 73 | public static long parseUI16(byte[] val) { | |
| 74 | return bytesToLong(new byte[] { val[0], val[1] }, false); | |
| 75 | } | |
| 76 | ||
| 77 | public static BitSet bitsUI24(long val) { | |
| 78 | Assert.inRange(val, MIN_UI24, MAX_UI24); | |
| 79 | return flipBytes(longToBits(val, 24), 3); | |
| 80 | } | |
| 81 | ||
| 82 | public static byte[] bytesUI24(long val) { | |
| 83 | return bitsToBytes(bitsUI24(val), 24); | |
| 84 | } | |
| 85 | ||
| 86 | public static long parseUI24(byte[] val) { | |
| 87 | return bytesToLong(new byte[] { val[0], val[1], val[2] }, false); | |
| 88 | } | |
| 89 | ||
| 90 | public static BitSet bitsUI32(long val) { | |
| 91 | Assert.inRange(val, MIN_UI32, MAX_UI32); | |
| 92 | return flipBytes(longToBits(val, 32), 4); | |
| 93 | } | |
| 94 | ||
| 95 | public static byte[] bytesUI32(long val) { | |
| 96 | return bitsToBytes(bitsUI32(val), 32); | |
| 97 | } | |
| 98 | ||
| 99 | public static long parseUI32(byte[] val) { | |
| 100 | return bytesToLong(new byte[] { val[0], val[1], val[2], val[3] }, false); | |
| 101 | } | |
| 102 | ||
| 103 | public static BitSet bitsSI8(long val) { | |
| 104 | Assert.inRange(val, MIN_SI8, MAX_SI8); | |
| 105 | return longToBits(val, 8); | |
| 106 | } | |
| 107 | ||
| 108 | public static byte[] bytesSI8(long val) { | |
| 109 | return bitsToBytes(bitsSI8(val), 8); | |
| 110 | } | |
| 111 | ||
| 112 | public static long parseSI8(byte[] val) { | |
| 113 | return bytesToLong(new byte[] { val[0] }, true); | |
| 114 | } | |
| 115 | ||
| 116 | public static BitSet bitsSI16(long val) { | |
| 117 | Assert.inRange(val, MIN_SI16, MAX_SI16); | |
| 118 | return flipBytes(longToBits(val, 16), 2); | |
| 119 | } | |
| 120 | ||
| 121 | public static byte[] bytesSI16(long val) { | |
| 122 | return bitsToBytes(bitsSI16(val), 16); | |
| 123 | } | |
| 124 | ||
| 125 | public static long parseSI16(byte[] val) { | |
| 126 | return bytesToLong(new byte[] { val[0], val[1] }, true); | |
| 127 | } | |
| 128 | ||
| 129 | public static BitSet bitsSI32(long val) { | |
| 130 | Assert.inRange(val, MIN_SI32, MAX_SI32); | |
| 131 | return flipBytes(longToBits(val, 32), 4); | |
| 132 | } | |
| 133 | ||
| 134 | public static byte[] bytesSI32(long val) { | |
| 135 | return bitsToBytes(bitsSI32(val), 32); | |
| 136 | } | |
| 137 | ||
| 138 | public static byte[] bytesSTRING(String val) { | |
| 139 | try { | |
| 140 | if (val == null || val.equals("")) { | |
| 141 | return new byte[] { 0x00 }; | |
| 142 | } | |
| 143 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |