/*
 * Copyright (c) 2007, intarsys consulting GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - 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.
 *
 * - Neither the name of intarsys nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
 */
package de.intarsys.tools.collection;

public class ByteArrayTools {

	public static byte[] concat(byte[] array1, byte[] array2) {
		byte[] concat = new byte[array1.length + array2.length];
		System.arraycopy(array1, 0, concat, 0, array1.length);
		System.arraycopy(array2, 0, concat, array1.length, array2.length);
		return concat;
	}

	/**
	 * Make a copy of <code>bytes</code>.
	 * 
	 * @param bytes
	 *            byte[] to be copied
	 * 
	 * @return A copy of <code>bytes</code>
	 */
	static public byte[] copy(byte[] bytes) {
		byte[] newbuf = new byte[bytes.length];
		System.arraycopy(bytes, 0, newbuf, 0, bytes.length);
		return newbuf;
	}

	/**
	 * Copy <code>length</code> bytes from <code>bytes</code> starting at
	 * <code>from</code>.
	 * 
	 * @param bytes
	 *            byte[] to be copied
	 * @param offset
	 *            starting position to copy from
	 * @param length
	 *            number of bytes
	 * 
	 * @return A copy of <code>bytes</code>
	 */
	static public byte[] copy(byte[] bytes, int offset, int length) {
		byte[] newbuf = new byte[length];
		System.arraycopy(bytes, offset, newbuf, 0, length);
		return newbuf;
	}

	/**
	 * Search index of pattern in source. Algorithm from java.lang.String
	 * 
	 * @param source
	 * @param sourceOffset
	 * @param sourceLen
	 * @param pattern
	 * @param patternOffset
	 * @param patternLen
	 * @param fromIndex
	 * @return The index of the first occurrence of pattern or -1.
	 */
	static public int indexOf(byte[] source, int sourceOffset, int sourceLen,
			byte[] pattern, int patternOffset, int patternLen, int fromIndex) {
		if (fromIndex >= sourceLen) {
			return (patternLen == 0 ? sourceLen : -1);
		}
		if (fromIndex < 0) {
			fromIndex = 0;
		}
		if (patternLen == 0) {
			return fromIndex;
		}

		byte first = pattern[patternOffset];
		int max = sourceOffset + (sourceLen - patternLen);

		for (int i = sourceOffset + fromIndex; i <= max; i++) {
			/* Look for first byte . */
			if (source[i] != first) {
				while (++i <= max && source[i] != first) {
					;
				}
			}

			/* Found first byte, now look at the rest of v2 */
			if (i <= max) {
				int j = i + 1;
				int end = j + patternLen - 1;
				for (int k = patternOffset + 1; j < end
						&& source[j] == pattern[k]; j++, k++) {
					;
				}

				if (j == end) {
					/* Found whole pattern. */
					return i - sourceOffset;
				}
			}
		}
		return -1;
	}

	/**
	 * <code>true</code> if <code>bytes</code> starts with the byte sequence
	 * defined in <code>pattern</code>.
	 * 
	 * @param bytes
	 * @param pattern
	 * @return <code>true</code> if <code>bytes</code> starts with the byte
	 *         sequence defined in <code>pattern</code>.
	 * 
	 */
	static public boolean startsWith(byte[] bytes, byte[] pattern) {
		if (bytes == null) {
			return false;
		}
		if (pattern == null) {
			return true;
		}
		int length = pattern.length;
		for (int i = 0; i < length; i++) {
			if (bytes[i] != pattern[i]) {
				return false;
			}
		}
		return true;
	}
}
