/**
 * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
 * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
 * joint initiative of the Federal Chancellery Austria and Graz University of
 * Technology.
 *
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
 * the European Commission - subsequent versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 * http://www.osor.eu/eupl/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 *
 * This product combines work with different licenses. See the "NOTICE" text
 * file for details on the various modules and licenses.
 * The "NOTICE" text file is part of the distribution. Any derivative works
 * that you distribute must include a readable copy of the "NOTICE" text file.
 *
 * $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;
  }

}