/* * (c) Copyright 2007, 2008, 2009 Hewlett-Packard Development Company, LP * All rights reserved. * [See end of file] */ package atlas.lib; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; /** Byte-oriented operations. Packing and unpacking integers * is in network order (Big endian - which is the preferred order in Java) * {@link "http://en.wikipedia.org/wiki/Endianness"} */ public class Bytes { private Bytes() {} // http://en.wikipedia.org/wiki/Endianness // Java is, by default, network order (big endian) // i.e what you get from ByteBuffer.allocate/.allocateDirect(); public static void main(String ... args) { ByteBuffer bb = ByteBuffer.allocate(8) ; System.out.println("Native order = "+ByteOrder.nativeOrder()) ; System.out.println("Default order = "+bb.order()) ; //bb.order(ByteOrder.BIG_ENDIAN) ; //bb.order(ByteOrder.LITTLE_ENDIAN) ; System.out.println("Order = "+bb.order()) ; bb.asLongBuffer().put(0x0102030405060708L) ; for ( int i = 0 ; i < bb.capacity(); i++ ) System.out.printf("0x%02X ",bb.get(i)) ; // Comes out hight to low : 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 } final public static byte[] hexDigits = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' // , 'g' , 'h' , // 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , // 'o' , 'p' , 'q' , 'r' , 's' , 't' , // 'u' , 'v' , 'w' , 'x' , 'y' , 'z' }; /** Get an int from a byte array (network order) * @param b Byte Array */ public static final int getInt(byte[]b) { return getInt(b, 0) ; } /** Get an int from a byte array (network order) * @param b Byte Array * @param idx Starting point of bytes */ public static final int getInt(byte[]b, int idx) { return assembleInt(b[idx+0], b[idx+1], b[idx+2], b[idx+3]) ; } /** Get a long from a byte array (network order) * @param b Byte Array */ public static final long getLong(byte[]b) { return getLong(b, 0) ; } /** Get a long from a byte array (network order) * @param b Byte Array * @param idx Starting point of bytes */ public static final long getLong(byte[]b, int idx) { return assembleLong(b[idx+0], b[idx+1], b[idx+2], b[idx+3], b[idx+4], b[idx+5], b[idx+6], b[idx+7]) ; } /** Put an int into a byte array * @param value The integer * @param b byte array */ public static final void setInt(int value, byte[]b) { setInt(value, b, 0) ; } /** Put an int into a byte array from a given position * @param x The integer * @param b byte array * @param idx starting point */ public static final void setInt(int x, byte[]b, int idx) { // b[idx+0] = byte3(value) ; // b[idx+1] = byte2(value) ; // b[idx+2] = byte1(value) ; // b[idx+3] = byte0(value) ; b[idx+0] = (byte)((x >> 24)&0xFF) ; b[idx+1] = (byte)((x >> 16)&0xFF); b[idx+2] = (byte)((x >> 8)&0xFF); b[idx+3] = (byte)(x &0xFF); } /** Put a long into a byte array * @param value The integer * @param b byte array */ public static final void setLong(long value, byte[]b) { setLong(value, b, 0) ; } /** Put a long into a byte array from a given position * @param value The integer * @param b byte array * @param idx starting point */ public static final void setLong(long value, byte[]b, int idx) { int lo = (int)(value&0xFFFFFFFFL) ; int hi = (int)(value>>>32) ; setInt(hi, b, idx) ; setInt(lo, b, idx+4) ; } /** int to byte array */ public static byte[] packInt(int val) { byte[] valBytes = new byte[Integer.SIZE/Byte.SIZE] ; setInt(val, valBytes, 0) ; return valBytes ; } /** long to byte array */ public static byte[] packLong(long val) { byte[] valBytes = new byte[Long.SIZE/Byte.SIZE] ; setLong(val, valBytes, 0) ; return valBytes ; } /** Make an int order of args -- high to low */ static private int assembleInt(byte b3, byte b2, byte b1, byte b0) { return ( ((b3 & 0xFF) << 24) | ((b2 & 0xFF) << 16) | ((b1 & 0xFF) << 8) | ((b0 & 0xFF) << 0) ); } /** Make a long order of args -- high to low */ static private Long assembleLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) { return (((long)b7 & 0xFF) << 56) | (((long)b6 & 0xFF) << 48) | (((long)b5 & 0xFF) << 40) | (((long)b4 & 0xFF) << 32) | (((long)b3 & 0xFF) << 24) | (((long)b2 & 0xFF) << 16) | (((long)b1 & 0xFF) << 8) | (((long)b0 & 0xFF) << 0) ; } private static byte byte3(int x) { return (byte)(x >> 24); } private static byte byte2(int x) { return (byte)(x >> 16); } private static byte byte1(int x) { return (byte)(x >> 8); } private static byte byte0(int x) { return (byte)(x >> 0); } /** Return the UTF-8 bytes for a string */ public static byte[] string2bytes(String x) { try { return x.getBytes("UTF-8") ; } catch (UnsupportedEncodingException ex) { // Impossible. ex.printStackTrace(); return null ; } } /** Return the string for some UTF-8 bytes */ public static String bytes2string(byte[] x) { try { return new String(x, "UTF-8") ; } catch (UnsupportedEncodingException ex) { // Impossible-ish. ex.printStackTrace(); return null ; } } /** Encode a string into a ByteBuffer */ public static void toByteBuffer(CharSequence s, ByteBuffer bb) { CharsetEncoder enc = Chars.getEncoder(); // Blocking finite Pool - does not happen. // Plain Pool (sync wrapped) - might - allocate an extra one. if ( enc == null ) enc = Chars.createEncoder() ; // enc = enc.onMalformedInput(CodingErrorAction.REPLACE) // .onUnmappableCharacter(CodingErrorAction.REPLACE); toByteBuffer(s, bb, enc) ; Chars.putEncoder(enc) ; } /** Encode a string into a ByteBuffer */ public static void toByteBuffer(CharSequence s, ByteBuffer bb, CharsetEncoder enc) { CharBuffer cBuff = CharBuffer.wrap(s); CoderResult r = enc.encode(cBuff, bb, true) ; if ( r.isOverflow() ) throw new InternalErrorException("Bytes.toByteBuffer: encode overflow (1)") ; r = enc.flush(bb) ; if ( r.isOverflow() ) throw new InternalErrorException("Bytes.toByteBuffer: encode overflow (2)") ; enc.reset(); } /** Decode a string into a ByteBuffer */ public static String fromByteBuffer(ByteBuffer bb) { CharsetDecoder dec = Chars.getDecoder(); if ( dec == null ) dec = Chars.createDecoder() ; String x = fromByteBuffer(bb, dec) ; Chars.putDecoder(dec) ; return x ; } /** Decode a string into a ByteBuffer */ public static String fromByteBuffer(ByteBuffer bb, CharsetDecoder dec) { if ( bb.remaining() == 0 ) return "" ; try { CharBuffer cBuff = dec.decode(bb) ; // No need to flush - the packaged form decode(ByteBuffer) does that. // CoderResult r = dec.flush(cBuff) ; // If no bytes, crashes here (illegal state). // if ( r == CoderResult.OVERFLOW ) // throw new InternalError("Bytes.fromByteBuffer: decode overflow") ; dec.reset() ; // Yuk - another copy. return cBuff.toString() ; } catch (CharacterCodingException ex) { throw new InternalErrorException("Bytes:fromByteBuffer: character encoding error in buffer") ; } } /** Return a hex string representing the bytes, zero padded to length of byte array. */ public static String asHex(byte[] bytes) { return asHex(bytes, 0, bytes.length) ; } public static String asHex(byte[] bytes, int start, int finish) { StringBuilder sw = new StringBuilder() ; for ( int i = start ; i < finish ; i++ ) { byte b = bytes[i] ; int hi = b >> 4 ; int lo = b & 0xF ; sw.append(Chars.hexDigits[hi]) ; sw.append(Chars.hexDigits[lo]) ; } return sw.toString() ; } public static int hexCharToInt(char c) { if ( '0' <= c && c <= '9' ) return c-'0' ; else if ( 'A' <= c && c <= 'F' ) return c-'A'+10 ; else if ( 'a' <= c && c <= 'f' ) return c-'a'+10 ; else throw new IllegalArgumentException("Bad index char : "+c) ; } } /* * (c) Copyright 2007, 2008, 2009 Hewlett-Packard Development Company, LP * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */