/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/metaobj/trunk/metaobj-impl/api-impl/src/java/org/sakaiproject/metaobj/utils/id/guid/ByteOrder.java $ * $Id: ByteOrder.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2004, 2005, 2006, 2008 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.sakaiproject.metaobj.utils.id.guid; /** * Various static routines for solving endian problems. */ public class ByteOrder { private static final int UNSIGNED_BYTE_MASK = 0x000000FF; /** * Returns the reverse of x. */ public static byte[] reverse(byte[] x) { int n = x.length; byte[] ret = new byte[n]; for (int i = 0; i < n; i++) { ret[i] = x[n - i - 1]; } return ret; } /** * Little-endian bytes to short * * @requires x.length-offset>=2 * @effects returns the value of x[offset..offset+2] as a short, * assuming x is interpreted as a signed little endian number (i.e., * x[offset] is LSB). If you want to interpret it as an unsigned number, * call ubytes2int on the result. */ public static short leb2short(byte[] x, int offset) { int x0 = (x[offset]) & UNSIGNED_BYTE_MASK; int x1 = (x[offset + 1] << 8); return (short) (x1 | x0); } /** * Little-endian bytes to int * * @requires x.length-offset>=4 * @effects returns the value of x[offset..offset+4] as an int, * assuming x is interpreted as a signed little endian number (i.e., * x[offset] is LSB) If you want to interpret it as an unsigned number, * call ubytes2int on the result. */ public static int leb2int(byte[] x, int offset) { //Must mask value after left-shifting, since case from byte //to int copies most significant bit to the left! int x0 = x[offset] & UNSIGNED_BYTE_MASK; int x1 = (x[offset + 1] << 8) & 0x0000FF00; int x2 = (x[offset + 2] << 16) & 0x00FF0000; int x3 = (x[offset + 3] << 24); return x3 | x2 | x1 | x0; } /** * Short to little-endian bytes: writes x to buf[offset...] */ public static void short2leb(short x, byte[] buf, int offset) { buf[offset] = (byte) (x & (short) 0x00FF); buf[offset + 1] = (byte) ((short) (x >> 8) & (short) 0x00FF); } /** * Int to little-endian bytes: writes x to buf[offset..] */ public static void int2leb(int x, byte[] buf, int offset) { buf[offset] = (byte) (x & UNSIGNED_BYTE_MASK); buf[offset + 1] = (byte) ((x >> 8) & UNSIGNED_BYTE_MASK); buf[offset + 2] = (byte) ((x >> 16) & UNSIGNED_BYTE_MASK); buf[offset + 3] = (byte) ((x >> 24) & UNSIGNED_BYTE_MASK); } /** * Interprets the value of x as an unsigned byte, and returns * it as integer. For example, ubyte2int(0xFF)==255, not -1. */ public static int ubyte2int(byte x) { return ((int) x) & UNSIGNED_BYTE_MASK; } /** * Interprets the value of x as am unsigned two-byte number */ public static int ubytes2int(short x) { return ((int) x) & 0x0000FFFF; } /** * Interprets the value of x as an unsigned two-byte number */ public static long ubytes2long(int x) { return ((long) x) & 0x00000000FFFFFFFFl; } /** * Returns the int value that is closest to l. That is, if l can fit into a * 32-bit unsigned number, returns (int)l. Otherwise, returns either * Integer.MAX_VALUE or Integer.MIN_VALUE as appropriate. */ public static int long2int(long l) { if (l >= Integer.MAX_VALUE) { return Integer.MAX_VALUE; } else if (l <= Integer.MIN_VALUE) { return Integer.MIN_VALUE; } else { return (int) l; } } /** Unit test */ /* public static void main(String args[]) { byte[] x1={(byte)0x2, (byte)0x1}; //{x1[0], x1[1]} short result1=leb2short(x1,0); Assert.that(result1==(short)258, "result1="+result1 ); //256+2; byte[] x1b=new byte[2]; short2leb(result1, x1b, 0); for (int i=0; i<2; i++) Assert.that(x1b[i]==x1[i]); byte[] x2={(byte)0x2, (byte)0, (byte)0, (byte)0x1}; //2^24+2 = 16777216+2 = 16777218 int result2=leb2int(x2,0); Assert.that(result2==16777218, "result2="+result2); byte[] x2b=new byte[4]; int2leb(result2, x2b, 0); for (int i=0; i<4; i++) Assert.that(x2b[i]==x2[i]); byte[] x3={(byte)0x00, (byte)0xF3, (byte)0, (byte)0xFF}; int result3=leb2int(x3,0); Assert.that(result3==0xFF00F300, Integer.toHexString(result3)); byte[] x4={(byte)0xFF, (byte)0xF3}; short result4=leb2short(x4,0); Assert.that(result4==(short)0xF3FF, Integer.toHexString(result4)); byte in=(byte)0xFF; //255 if unsigned, -1 if signed. int out=(int)in; Assert.that(out==-1, out+""); out=ubyte2int(in); Assert.that(out==255, out+""); out=ubyte2int((byte)1); Assert.that(out==1, out+""); short in2=(short)0xFFFF; Assert.that(in2<0,"L122"); Assert.that(ubytes2int(in2)==0x0000FFFF, "L123"); Assert.that(ubytes2int(in2)>0, "L124"); int in3=(int)0xFFFFFFFF; Assert.that(in3<0, "L127"); Assert.that(ubytes2long(in3)==0x00000000FFFFFFFFl, "L128"); Assert.that(ubytes2long(in3)>0, "L129"); byte[] buf={(byte)0xFF, (byte)0xFF}; in2=leb2short(buf,0); Assert.that(in2==-1, "L133: "+Integer.toHexString(in2)); int out2=ubytes2int(in2); Assert.that(out2==0x0000FFFF, "L134: "+out); byte[] buf2={(byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF}; in3=leb2int(buf2,0); Assert.that(in3==-1, "L139"); long out4=ubytes2long(in3); Assert.that(out4==0x00000000FFFFFFFFl, "L141"); Assert.that(long2int(5l)==5); Assert.that(long2int(-10l)==-10); Assert.that(long2int(0l)==0); Assert.that(long2int(0xABFFFFFFFFl)==0x7FFFFFFF); //Integer.MAX_VALUE Assert.that(long2int(-0xABFFFFFFFFl)==0x80000000); //Integer.MIN_VALUE } */ }