content: /*-
   * Copyright (C) 2006-2007 Erik Larsson
   * 
   * 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 3 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, see <http://www.gnu.org/licenses/>.
   */
  
  package org.catacombae.dmgextractor;
  import java.io.*;
  
  public class Util {
      public static int sectorSize = 0x800;
      
      /**
       * Tests whether the current VM is a Java 6 or higher VM.
       * @return
       */
      public static boolean isJava6OrHigher() {
      	return System.getProperty("java.vm.version").compareTo("1.6") >= 0;
      }
  
      public static String byteArrayToHexString(byte[] array) {
  	return byteArrayToHexString(array, 0, array.length);
      }
      public static String byteArrayToHexString(byte[] array, int offset, int length) {
  	String result = "";
  	for(int i = offset; i < (offset+length); ++i) {
  	    byte b = array[i];
  	    String currentHexString = Integer.toHexString(b & 0xFF);
  	    if(currentHexString.length() == 1)
  		currentHexString = "0" + currentHexString;
  	    result += currentHexString;
  	}
  	return result;
      }
  
      public static String toHexStringBE(char[] array) {
  	return toHexStringBE(array, 0, array.length);
      }
      public static String toHexStringBE(char[] array, int offset, int length) {
  	StringBuilder result = new StringBuilder();
  	for(int i = offset; i < length; ++i)
  	    result.append(toHexStringBE(array[i]));
  	return result.toString();
      }
      public static String toHexStringBE(short[] array) {
  	return toHexStringBE(array, 0, array.length);
      }
      public static String toHexStringBE(short[] array, int offset, int length) {
  	StringBuilder result = new StringBuilder();
  	for(int i = offset; i < length; ++i)
  	    result.append(toHexStringBE(array[i]));
  	return result.toString();
      }
      public static String toHexStringBE(int[] array) {
  	return toHexStringBE(array, 0, array.length);
      }
      public static String toHexStringBE(int[] array, int offset, int length) {
  	StringBuilder result = new StringBuilder();
  	for(int i = offset; i < length; ++i)
  	    result.append(toHexStringBE(array[i]));
  	return result.toString();
      }
  
      public static String toHexStringLE(byte n) { return byteArrayToHexString(toByteArrayLE(n)); }
      public static String toHexStringLE(short n) { return byteArrayToHexString(toByteArrayLE(n)); }
      public static String toHexStringLE(char n) { return byteArrayToHexString(toByteArrayLE(n)); }
      public static String toHexStringLE(int n) { return byteArrayToHexString(toByteArrayLE(n)); }
      public static String toHexStringLE(long n) { return byteArrayToHexString(toByteArrayLE(n)); }
      public static String toHexStringBE(byte n) { return byteArrayToHexString(toByteArrayBE(n)); }
      public static String toHexStringBE(short n) { return byteArrayToHexString(toByteArrayBE(n)); }
      public static String toHexStringBE(char n) { return byteArrayToHexString(toByteArrayBE(n)); }
      public static String toHexStringBE(int n) { return byteArrayToHexString(toByteArrayBE(n)); }
      public static String toHexStringBE(long n) { return byteArrayToHexString(toByteArrayBE(n)); }
  
      public static byte[] invert(byte[] array) {
  	byte[] newArray = new byte[array.length];
  	for(int i = 0; i < array.length; ++i)
  	    newArray[newArray.length-i-1] = array[i];
  	return newArray;
      }
  
      public static long readLongLE(byte[] data) {
  	return readLongLE(data, 0);
      }
      public static long readLongLE(byte[] data, int offset) {
  	return (((long)data[offset+7] & 0xFF) << 56 |
  		((long)data[offset+6] & 0xFF) << 48 |
  		((long)data[offset+5] & 0xFF) << 40 |
  		((long)data[offset+4] & 0xFF) << 32 |
  		((long)data[offset+3] & 0xFF) << 24 |
  		((long)data[offset+2] & 0xFF) << 16 |
  		((long)data[offset+1] & 0xFF) << 8 |
  		((long)data[offset+0] & 0xFF) << 0);
      }
      public static int readIntLE(byte[] data) {
  	return readIntLE(data, 0);
      }
      public static int readIntLE(byte[] data, int offset) {
  	return ((data[offset+3] & 0xFF) << 24 |
  		(data[offset+2] & 0xFF) << 16 |
  		(data[offset+1] & 0xFF) << 8 |
  		(data[offset+0] & 0xFF) << 0);
      }
      public static short readShortLE(byte[] data) {
  	return readShortLE(data, 0);
      }
      public static short readShortLE(byte[] data, int offset) {
  	return (short) ((data[offset+1] & 0xFF) << 8 |
  			(data[offset+0] & 0xFF) << 0);
      }
      public static byte readByteLE(byte[] data) {
  	return readByteLE(data, 0);
      }
      public static byte readByteLE(byte[] data, int offset) {
  	return data[offset];
      }
      public static long readLongBE(byte[] data) {
  	return readLongBE(data, 0);
      }
  
  //     public static void main(String[] args) {
  // 	byte[] longTest1 = { 0, 0, 0, 0, 0, 0, 0, 13 };
  // 	byte[] longTest2 = { 0, 31, 0, 0, 0, 0, 0, 0 };
  // 	byte[] longTest3 = { 127, 0, 0, 0, 0, 0, 0, 0 };
  // 	byte[] longTest4 = { 0, 0, 0, 1, 1, 1, 1, 1 };
  // 	System.out.println("longTest1: " + readLongBE(longTest1));
  // 	System.out.println("longTest2: " + readLongBE(longTest2));
  // 	System.out.println("longTest3: " + readLongBE(longTest3));
  // 	System.out.println("longTest4: " + readLongBE(longTest4));
  //     }
  
      public static long readLongBE(byte[] data, int offset) {
  // 	if(false) {
  // 	    long d1 = (data[offset+0] & 0xFFL) << 56;
  // 	    long d2 = (data[offset+1] & 0xFFL) << 48;
  // 	    long d3 = (data[offset+2] & 0xFFL) << 40;
  // 	    long d4 = (data[offset+3] & 0xFFL) << 32;
  // 	    long d5 = (data[offset+4] & 0xFFL) << 24;
  // 	    long d6 = (data[offset+5] & 0xFFL) << 16;
  // 	    long d7 = (data[offset+6] & 0xFFL) << 8;
  // 	    long d8 = (data[offset+7] & 0xFFL) << 0;
  // 	    System.out.println("1. 0x" + toHexStringBE(d1));
  // 	    System.out.println("2. 0x" + toHexStringBE(d2));
  // 	    System.out.println("3. 0x" + toHexStringBE(d3));
  // 	    System.out.println("4. 0x" + toHexStringBE(d4));
  // 	    System.out.println("5. 0x" + toHexStringBE(d5));
  // 	    System.out.println("6. 0x" + toHexStringBE(d6));
  // 	    System.out.println("7. 0x" + toHexStringBE(d7));
  // 	    System.out.println("8. 0x" + toHexStringBE(d8));
  // 	    return d1 | d2 | d3 | d4 | d5 | d6 | d7 | d8;
  // 	}
  // 	else {
  	return (((long)data[offset+0] & 0xFF) << 56 |
  		((long)data[offset+1] & 0xFF) << 48 |
  		((long)data[offset+2] & 0xFF) << 40 |
  		((long)data[offset+3] & 0xFF) << 32 |
  		((long)data[offset+4] & 0xFF) << 24 |
  		((long)data[offset+5] & 0xFF) << 16 |
  		((long)data[offset+6] & 0xFF) << 8 |
  		((long)data[offset+7] & 0xFF) << 0);
  // 	}
      }
      public static int readIntBE(byte[] data) {
  	return readIntBE(data, 0);
      }
      public static int readIntBE(byte[] data, int offset) {
  	return ((data[offset+0] & 0xFF) << 24 |
  		(data[offset+1] & 0xFF) << 16 |
  		(data[offset+2] & 0xFF) << 8 |
  		(data[offset+3] & 0xFF) << 0);
      }
      public static short readShortBE(byte[] data) {
  	return readShortBE(data, 0);
      }
      public static short readShortBE(byte[] data, int offset) {
  	return (short) ((data[offset+0] & 0xFF) << 8 |
  			(data[offset+1] & 0xFF) << 0);
      }
      public static byte readByteBE(byte[] data) {
  	return readByteBE(data, 0);
      }
      public static byte readByteBE(byte[] data, int offset) {
  	return data[offset];
      }
  
      public static byte[] toByteArrayLE(byte b) {
  	byte[] result = new byte[1];
  	result[0] = b;
  	return result;
      }
      public static byte[] toByteArrayLE(short s) {
  	byte[] result = new byte[2];
  	result[0] = (byte) ((s >> 0) & 0xFF);
  	result[1] = (byte) ((s >> 8) & 0xFF);
  	return result;
      }
      public static byte[] toByteArrayLE(char c) {
  	byte[] result = new byte[2];
  	result[0] = (byte) ((c >> 0) & 0xFF);
  	result[1] = (byte) ((c >> 8) & 0xFF);
  	return result;
      }
      public static byte[] toByteArrayLE(int i) {
  	byte[] result = new byte[4];
  	result[0] = (byte) ((i >> 0) & 0xFF);
  	result[1] = (byte) ((i >> 8) & 0xFF);
  	result[2] = (byte) ((i >> 16) & 0xFF);
  	result[3] = (byte) ((i >> 24) & 0xFF);
  	return result;
      }
      public static byte[] toByteArrayLE(long l) {
  	byte[] result = new byte[8];
  	result[0] = (byte) ((l >> 0) & 0xFF);
  	result[1] = (byte) ((l >> 8) & 0xFF);
  	result[2] = (byte) ((l >> 16) & 0xFF);
  	result[3] = (byte) ((l >> 24) & 0xFF);
  	result[4] = (byte) ((l >> 32) & 0xFF);
  	result[5] = (byte) ((l >> 40) & 0xFF);
  	result[6] = (byte) ((l >> 48) & 0xFF);
  	result[7] = (byte) ((l >> 56) & 0xFF);
  	return result;
      }
      public static byte[] toByteArrayBE(byte b) {
  	byte[] result = new byte[1];
  	result[0] = b;
  	return result;
      }
      public static byte[] toByteArrayBE(short s) {
  	byte[] result = new byte[2];
  	result[0] = (byte) ((s >> 8) & 0xFF);
  	result[1] = (byte) ((s >> 0) & 0xFF);
  	return result;
      }
      public static byte[] toByteArrayBE(char c) {
  	byte[] result = new byte[2];
  	result[0] = (byte) ((c >> 8) & 0xFF);
  	result[1] = (byte) ((c >> 0) & 0xFF);
  	return result;
      }
      public static byte[] toByteArrayBE(int i) {
  	byte[] result = new byte[4];
  	result[0] = (byte) ((i >> 24) & 0xFF);
  	result[1] = (byte) ((i >> 16) & 0xFF);
  	result[2] = (byte) ((i >> 8) & 0xFF);
  	result[3] = (byte) ((i >> 0) & 0xFF);
  	return result;
      }
      public static byte[] toByteArrayBE(long l) {
  	byte[] result = new byte[8];
  	result[0] = (byte) ((l >> 56) & 0xFF);
  	result[1] = (byte) ((l >> 48) & 0xFF);
  	result[2] = (byte) ((l >> 40) & 0xFF);
  	result[3] = (byte) ((l >> 32) & 0xFF);
  	result[4] = (byte) ((l >> 24) & 0xFF);
  	result[5] = (byte) ((l >> 16) & 0xFF);
  	result[6] = (byte) ((l >> 8) & 0xFF);
  	result[7] = (byte) ((l >> 0) & 0xFF);
  	return result;
      }
  
      public static boolean zeroed(byte[] ba) {
  	for(byte b : ba)
  	    if(b != 0)
  		return false;
  	return true;
      }
  
      public static void zero(byte[]... arrays) {
          for(byte[] ba : arrays)
              set(ba, 0, ba.length, (byte)0);
      }
      public static void zero(byte[] ba, int offset, int length) {
          set(ba, offset, length, (byte)0);
      }
      public static void zero(short[]... arrays) {
          for(short[] array : arrays)
              set(array, 0, array.length, (short)0);
      }
      public static void zero(short[] ba, int offset, int length) {
          set(ba, offset, length, (short)0);
      }
      public static void zero(int[]... arrays) {
          for(int[] array : arrays)
              set(array, 0, array.length, (int) 0);
      }
      public static void zero(int[] ba, int offset, int length) {
          set(ba, offset, length, (int) 0);
      }
      public static void zero(long[]... arrays) {
          for(long[] array : arrays)
              set(array, 0, array.length, (long) 0);
      }
      public static void zero(long[] ba, int offset, int length) {
          set(ba, offset, length, (long) 0);
      }
  
      public static void set(boolean[] array, boolean value) {
          set(array, 0, array.length, value);
      }
  
      public static void set(byte[] array, byte value) {
          set(array, 0, array.length, value);
      }
  
      public static void set(short[] array, short value) {
          set(array, 0, array.length, value);
      }
  
      public static void set(char[] array, char value) {
          set(array, 0, array.length, value);
      }
  
      public static void set(int[] array, int value) {
          set(array, 0, array.length, value);
      }
  
      public static void set(long[] array, long value) {
          set(array, 0, array.length, value);
      }
  
      public static <T> void set(T[] array, T value) {
          set(array, 0, array.length, value);
      }
  
      public static void set(boolean[] ba, int offset, int length, boolean value) {
  	for(int i = offset; i < length; ++i)
  	    ba[i] = value;
      }
  
      public static void set(byte[] ba, int offset, int length, byte value) {
  	for(int i = offset; i < length; ++i)
  	    ba[i] = value;
      }
  
      public static void set(short[] ba, int offset, int length, short value) {
  	for(int i = offset; i < length; ++i)
  	    ba[i] = value;
      }
  
      public static void set(char[] ba, int offset, int length, char value) {
  	for(int i = offset; i < length; ++i)
  	    ba[i] = value;
      }
  
      public static void set(int[] ba, int offset, int length, int value) {
  	for(int i = offset; i < length; ++i)
  	    ba[i] = value;
      }
  
      public static void set(long[] ba, int offset, int length, long value) {
  	for(int i = offset; i < length; ++i)
  	    ba[i] = value;
      }
  
      public static <T> void set(T[] ba, int offset, int length, T value) {
  	for(int i = offset; i < length; ++i)
  	    ba[i] = value;
      }
  
      public static byte[] createCopy(byte[] data) {
  	return createCopy(data, 0, data.length);
      }
  
      public static byte[] createCopy(byte[] data, int offset, int length) {
  	byte[] copy = new byte[length];
  	System.arraycopy(data, offset, copy, 0, length);
  	return copy;
      }
  
      /**
       * Creates a copy of the input data reversed byte by byte. This is helpful for endian swapping.
       *
       * @param data
       * @return
       */
      public static byte[] createReverseCopy(byte[] data) {
  	return createReverseCopy(data, 0, data.length);
      }
  
      /**
       * Creates a copy of the input data reversed byte by byte. This is helpful for endian swapping.
       *
       * @param data
       * @param offset
       * @param length
       * @return
       */
      public static byte[] createReverseCopy(byte[] data, int offset, int length) {
  	byte[] copy = new byte[length];
  	for(int i = 0; i < copy.length; ++i) {
              copy[i] = data[offset+(length-i-1)];
          }
  	return copy;
      }
  
      public static byte[] arrayCopy(byte[] source, byte[] dest) {
  	return arrayCopy(source, dest, 0);
      }
  
      public static byte[] arrayCopy(byte[] source, byte[] dest, int destPos) {
  	if(dest.length-destPos < source.length)
  	    throw new RuntimeException("Destination array not large enough.");
  	System.arraycopy(source, 0, dest, 0, source.length);
          return dest;
      }
  
      public static <T> T[] arrayCopy(T[] source, T[] dest) {
          return arrayCopy(source, dest, 0);
      }
  
      public static <T> T[] arrayCopy(T[] source, T[] dest, int destPos) {
          if(dest.length-destPos < source.length)
  	    throw new RuntimeException("Destination array not large enough.");
  	System.arraycopy(source, 0, dest, 0, source.length);
          return dest;
      }
  
      public static boolean arraysEqual(boolean[] a, boolean[] b) {
  	return arrayRegionsEqual(a, 0, a.length, b, 0, b.length);
      }
      public static boolean arrayRegionsEqual(boolean[] a, int aoff, int alen,
  					    boolean[] b, int boff, int blen) {
  	if(alen != blen)
  	    return false;
  	else {
  	    for(int i = 0; i < alen; ++i)
  		if(a[aoff+i] != b[boff+i])
  		    return false;
  	    return true;
  	}
      }
      public static boolean arraysEqual(byte[] a, byte[] b) {
  	return arrayRegionsEqual(a, 0, a.length, b, 0, b.length);
      }
      public static boolean arrayRegionsEqual(byte[] a, int aoff, int alen,
  					    byte[] b, int boff, int blen) {
  	if(a.length != blen)
  	    return false;
  	else {
  	    for(int i = 0; i < alen; ++i)
  		if(a[aoff+i] != b[boff+i])
  		    return false;
  	    return true;
  	}
      }
      public static boolean arraysEqual(char[] a, char[] b) {
  	return arrayRegionsEqual(a, 0, a.length, b, 0, b.length);
      }
      public static boolean arrayRegionsEqual(char[] a, int aoff, int alen,
  					    char[] b, int boff, int blen) {
  	if(alen != blen)
  	    return false;
  	else {
  	    for(int i = 0; i < alen; ++i)
  		if(a[aoff+i] != b[boff+i])
  		    return false;
  	    return true;
  	}
      }
      public static boolean arraysEqual(short[] a, short[] b) {
  	return arrayRegionsEqual(a, 0, a.length, b, 0, b.length);
      }
      public static boolean arrayRegionsEqual(short[] a, int aoff, int alen,
  					    short[] b, int boff, int blen) {
  	if(alen != blen)
  	    return false;
  	else {
  	    for(int i = 0; i < alen; ++i)
  		if(a[aoff+i] != b[boff+i])
  		    return false;
  	    return true;
  	}
      }
      public static boolean arraysEqual(int[] a, int[] b) {
  	return arrayRegionsEqual(a, 0, a.length, b, 0, b.length);
      }
      public static boolean arrayRegionsEqual(int[] a, int aoff, int alen,
  					    int[] b, int boff, int blen) {
  	if(alen != blen)
  	    return false;
  	else {
  	    for(int i = 0; i < alen; ++i)
  		if(a[aoff+i] != b[boff+i])
  		    return false;
  	    return true;
  	}
      }
      public static boolean arraysEqual(long[] a, long[] b) {
  	return arrayRegionsEqual(a, 0, a.length, b, 0, b.length);
      }
      public static boolean arrayRegionsEqual(long[] a, int aoff, int alen,
  					    long[] b, int boff, int blen) {
  	if(alen != blen)
  	    return false;
  	else {
  	    for(int i = 0; i < alen; ++i)
  		if(a[aoff+i] != b[boff+i])
  		    return false;
  	    return true;
  	}
      }
      public static boolean arraysEqual(Object[] a, Object[] b) {
  	return arrayRegionsEqual(a, 0, a.length, b, 0, b.length);
      }
      public static boolean arrayRegionsEqual(Object[] a, int aoff, int alen,
  					    Object[] b, int boff, int blen) {
  	if(alen != blen)
  	    return false;
  	else {
  	    for(int i = 0; i < alen; ++i)
  		if(!a[aoff+i].equals(b[boff+i]))
  		    return false;
  	    return true;
  	}
      }
  
      public static long pow(long a, long b) {
  	if(b < 0) throw new IllegalArgumentException("b can not be negative");
  
  	long result = 1;
  	for(long i = 0; i < b; ++i)
  	    result *= a;
  	return result;
      }
  
      public static int strlen(byte[] data) {
  	int length = 0;
  	for(byte b : data) {
  	    if(b == 0)
  		break;
  	    else
  		++length;
  	}
  	return length;
      }
  
      public static boolean getBit(long data, int bitNumber) {
  	return ((data >>> bitNumber) & 0x1) == 0x1;
      }
  
      public static int arrayCompareLex(byte[] a, byte[] b) {
          return arrayCompareLex(a, 0, a.length, b, 0, b.length);
      }
  
      public static int arrayCompareLex(byte[] a, int aoff, int alen, byte[] b, int boff, int blen) {
          int compareLen = alen < blen ? alen : blen; // equiv. Math.min
  	for(int i = 0; i < compareLen; ++i) {
  	    byte curA = a[aoff+i];
  	    byte curB = b[boff+i];
  	    if(curA != curB)
  		return curA - curB;
  	}
  	return alen-blen; // The shortest array gets higher priority
      }
  
      public static int unsignedArrayCompareLex(char[] a, char[] b) {
  	return unsignedArrayCompareLex(a, 0, a.length, b, 0, b.length);
      }
  
      public static int unsignedArrayCompareLex(char[] a, int aoff, int alen, char[] b, int boff, int blen) {
  	int compareLen = alen < blen ? alen : blen; // equiv. Math.min
  	for(int i = 0; i < compareLen; ++i) {
  	    int curA = a[aoff+i] & 0xFFFF; // Unsigned char values represented as int
  	    int curB = b[boff+i] & 0xFFFF;
  	    if(curA != curB)
  		return curA - curB;
  	}
  	return alen-blen; // The shortest array gets higher priority
      }
  
      // All below is from Util2 (got tired of having two Util classes...)
      public static String toASCIIString(byte[] data) {
  	return toASCIIString(data, 0, data.length);
      }
      public static String toASCIIString(byte[] data, int offset, int length) {
  	return readString(data, offset, length, "US-ASCII");
      }
      public static String toASCIIString(short i) {
  	return toASCIIString(Util.toByteArrayBE(i));
      }
      public static String toASCIIString(int i) {
  	return toASCIIString(Util.toByteArrayBE(i));
      }
      public static String readString(byte[] data, String encoding) {
  	return readString(data, 0, data.length, encoding);
      }
      public static String readString(byte[] data, int offset, int length, String encoding) {
  	try {
  	    return new String(data, offset, length, encoding);
  	} catch(Exception e) {
  	    return null;
  	}
      }
      public static String readString(short i, String encoding) {
  	return readString(Util.toByteArrayBE(i), encoding);
      }
      public static String readString(int i, String encoding) {
  	return readString(Util.toByteArrayBE(i), encoding);
      }
  
      public static String readNullTerminatedASCIIString(byte[] data) {
  	return readNullTerminatedASCIIString(data, 0, data.length);
      }
  
      public static String readNullTerminatedASCIIString(byte[] data, int offset, int maxLength) {
  	int i;
  	for(i = offset; i < (offset+maxLength); ++i)
  	    if(data[i] == 0) break;
  	return toASCIIString(data, offset, i-offset);
      }
  
      public static char readCharLE(byte[] data) {
  	return readCharLE(data, 0);
      }
      public static char readCharLE(byte[] data, int offset) {
  	return (char) ((data[offset+1] & 0xFF) << 8 |
  		       (data[offset+0] & 0xFF) << 0);
      }
      public static char readCharBE(byte[] data) {
  	return readCharBE(data, 0);
      }
      public static char readCharBE(byte[] data, int offset) {
  	return (char) ((data[offset+0] & 0xFF) << 8 |
  		       (data[offset+1] & 0xFF) << 0);
      }
  
      public static byte[] readByteArrayBE(byte[] b) {
  	return createCopy(b);
      }
      public static char[] readCharArrayBE(byte[] b) {
  	char[] result = new char[b.length/2];
  	for(int i = 0; i < result.length; ++i)
  	    result[i] = Util.readCharBE(b, i*2);
  	return result;
      }
      public static short[] readShortArrayBE(byte[] b) {
  	short[] result = new short[b.length/2];
  	for(int i = 0; i < result.length; ++i)
  	    result[i] = Util.readShortBE(b, i*2);
  	return result;
      }
      public static int[] readIntArrayBE(byte[] b) {
  	int[] result = new int[b.length/4];
  	for(int i = 0; i < result.length; ++i)
  	    result[i] = Util.readIntBE(b, i*4);
  	return result;
      }
      public static long[] readLongArrayBE(byte[] b) {
  	long[] result = new long[b.length/8];
  	for(int i = 0; i < result.length; ++i)
  	    result[i] = Util.readLongBE(b, i*8);
  	return result;
      }
  
      public static byte[] readByteArrayLE(char[] data) {
  	return readByteArrayLE(data, 0, data.length);
      }
      public static byte[] readByteArrayLE(char[] data, int offset, int size) {
  	byte[] result = new byte[data.length*2];
  	for(int i = 0; i < data.length; ++i) {
  	    byte[] cur = toByteArrayLE(data[i]);
  	    result[i*2] = cur[0];
  	    result[i*2+1] = cur[1];
  	}
  	return result;
      }
      public static byte[] readByteArrayBE(char[] data) {
  	return readByteArrayBE(data, 0, data.length);
      }
      public static byte[] readByteArrayBE(char[] data, int offset, int size) {
  	byte[] result = new byte[data.length*2];
  	for(int i = 0; i < data.length; ++i) {
  	    byte[] cur = toByteArrayBE(data[i]);
  	    result[i*2] = cur[0];
  	    result[i*2+1] = cur[1];
  	}
  	return result;
      }
  
      public static byte[] fillBuffer(InputStream is, byte[] buffer) throws IOException {
  	DataInputStream dis = new DataInputStream(is);
  	dis.readFully(buffer);
  	return buffer;
      }
  
      public static short unsign(byte b) {
  	return (short)(b & 0xFF);
      }
      public static int unsign(short s) {
  	return s & 0xFFFF;
      }
      public static long unsign(int i) {
  	return i & 0xFFFFFFFFL;
      }
  
      
      // Added 2007-06-24 for DMGExtractor
      public static String readFully(Reader r) throws IOException {
  	StringBuilder sb = new StringBuilder();
  	char[] temp = new char[512];
  	long bytesRead = 0;
  	int curBytesRead = r.read(temp, 0, temp.length);
  	while(curBytesRead >= 0) {
  	    sb.append(temp, 0, curBytesRead);
  	    curBytesRead = r.read(temp, 0, temp.length);
  	}
  	return sb.toString();
      }
  
      // Added 2007-06-26 for DMGExtractor
      public static String[] concatenate(String[] a, String... b) {
  	String[] c = new String[a.length+b.length];
  	System.arraycopy(a, 0, c, 0, a.length);
  	System.arraycopy(b, 0, c, a.length, b.length);
  	return c;
      }
  
      // From IRCForME
      public static byte[] encodeString(String string, String encoding) {
  	try {
  	    return string.getBytes(encoding);
  	} catch(Exception e) { return null; }
      }
  
  }
  