/**
 * <copyright> Copyright (c) 2006 by Know-Center, Graz, Austria </copyright>
 * 
 * This software is the confidential and proprietary information of Know-Center,
 * Graz, Austria. You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Know-Center.
 * 
 * KNOW-CENTER MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. KNOW-CENTER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 * 
 * $Id: ByteArrayUtils.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
 */
package at.knowcenter.wag.exactparser;

import java.io.UnsupportedEncodingException;

/**
 * Abstract class that contains utility methods for handling byte arrays.
 * 
 * @author wprinz
 */
public abstract class ByteArrayUtils {

  public static final String BYTE_ARRAY_ENCODING = "ISO-8859-1";

  /**
   * Converts the byte array to a String.
   * 
   * @param data
   *          The byte array.
   * @return Returns the String.
   * @throws UnsupportedEncodingException
   *           Forwarded exception
   */
  public static String convertByteArrayToString(final byte[] data) throws UnsupportedEncodingException {
    return new String(data, BYTE_ARRAY_ENCODING);
  }

  /**
   * Finds the first occurance of search in data starting to search from the
   * given index.
   * 
   * @param data
   *          The big array.
   * @param index
   *          The index to start searching from.
   * @param search
   *          The sought array.
   * @return Returns the index of the found occurence or -1 if nothing was
   *         found.
   */
  public static int indexOf(final byte[] data, final int index, final byte[] search) {
    for (int i = index; i <= data.length - search.length; i++) {
      if (compareByteArrays(data, i, search)) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Finds the last occurance of the array.
   * 
   * @param data
   *          The source array to be searched.
   * @param search
   *          The sought array.
   * @return Returns the index of the last occurance - or -1 if nothing was
   *         found.
   */
  public static int lastIndexOf(final byte[] data, byte[] search) {
    for (int index = data.length - search.length; index >= 0; index--) {
      if (compareByteArrays(data, index, search)) {
        return index;
      }
    }
    return -1;
  }

  /**
   * Compares the two byte arrays for equality.
   * 
   * @param data
   *          The source array.
   * @param index
   *          In index into the source array marking where the comparison should
   *          start.
   * @param search
   *          The sought array.
   * @return Returns true if the first search.length bytes of data+index and
   *         search match exactly. Returns false otherwise.
   */
  public static boolean compareByteArrays(final byte[] data, final int index, byte[] search) {
    if (index < 0 || index >= data.length) {
      throw new IndexOutOfBoundsException("The index " + index + " is out of bounds");
    }

    if (search.length > data.length) {
      return false;
    }

    if (search.length > data.length - index) {
      return false;
    }

    for (int i = 0; i < search.length; i++) {
      if (data[index + i] != search[i]) {
        return false;
      }
    }

    return true;
  }

  /**
   * Checks, if the sought data byte is contained within the byte array.
   * 
   * @param byte_array
   *          The byte array.
   * @param data
   *          A data byte sought within the byte array.
   * @return Returns true, if the data byte was found (at least once) in the
   *         byte array, false otherwise.
   */
  public static boolean contains(final byte[] byte_array, final byte data) {
    for (int i = 0; i < byte_array.length; i++) {
      byte b =  byte_array[i];
      if (b == data) {
        return true;
      }
    }
    return false;
  }

}