/**
* Copyright (c) 2013-2014 Robert Maupin
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
package org.csdgn.maru;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
*
* @author Robert Maupin
*/
public class Bytes {
public static byte[] add(byte[] array, byte element) {
if (array == null) {
return null;
}
if (array.length == 0) {
return new byte[0];
}
final byte[] array2 = new byte[array.length + 1];
System.arraycopy(array, 0, array2, 0, array.length);
array2[array.length] = element;
return array2;
}
public static final Iterable<Byte> getIterable(final byte[] array) {
return new Iterable<Byte>() {
@Override
public Iterator<Byte> iterator() {
return getIterator(array);
}
};
}
public static final Iterator<Byte> getIterator(final byte[] array) {
// Ensure the error is found as soon as possible.
if (array == null) {
return null;
}
return new Iterator<Byte>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < array.length;
}
@Override
public Byte next() {
/*
* Throw NoSuchElementException as defined by the Iterator
* contract, not IndexOutOfBoundsException.
*/
if (!hasNext()) {
throw new NoSuchElementException();
}
return array[index++];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public static byte[] clone(byte[] array) {
if (array == null) {
return null;
}
if (array.length == 0) {
return new byte[0];
}
final byte[] array2 = new byte[array.length];
System.arraycopy(array, 0, array2, 0, array.length);
return array2;
}
private static int hexToByte(char c1, char c2) {
// nibble to numeric
int n0 = c1 - 48;
int n1 = c2 - 48;
if (n0 > 9) {
n0 -= 7;
}
if (n0 > 15) {
n0 -= 32;
}
if (n1 > 9) {
n1 -= 7;
}
if (n1 > 15) {
n1 -= 32;
}
return n0 << 4 | n1;
}
public static byte[] hexToBytes(String hex) {
hex = hex.trim();
if (hex.charAt(1) == 'x') {
hex = hex.substring(2);
}
// consume two characters at a time...
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Iterator<Character> it = Strings.getIterator(hex);
while (it.hasNext()) {
baos.write(hexToByte(it.next(), it.next()));
}
return baos.toByteArray();
}
public static String bytesToHex(byte[] array) {
StringBuilder sb = new StringBuilder();
for(byte b : array) {
sb.append(String.format("%02x",b));
}
return sb.toString();
}
public static boolean contains(byte[] array, byte value) {
return indexOf(array, value) != -1;
}
public static boolean contains(byte[] array, byte[] value) {
return indexOf(array, value) != -1;
}
public static int indexOf(byte[] array, byte value) {
return indexOf(array, value, 0);
}
public static int indexOf(byte[] array, byte value, int start) {
if (array == null) {
return -1;
}
if (array.length == 0) {
return -1;
}
if (start < 0) {
start = 0;
}
for (int i = start; i < array.length; ++i) {
if (value == array[i]) {
return i;
}
}
return -1;
}
public static int indexOf(byte[] array, byte[] value) {
return indexOf(array, value, 0);
}
public static int indexOf(byte[] array, byte[] value, int start) {
if (array == null || value == null) {
return -1;
}
if (array.length == 0 || value.length == 0) {
return -1;
}
if (start < 0) {
start = 0;
}
loop: for (int i = start; i < array.length - value.length + 1; ++i) {
for (int j = 0; j < value.length; j++) {
if (array[i + j] != value[j]) {
continue loop;
}
}
return i;
}
return -1;
}
public static byte[] join(byte[] array1, byte[] array2) {
if (array1 == null) {
return clone(array2);
}
if (array1.length == 0) {
return clone(array2);
}
if (array2 == null) {
return clone(array1);
}
if (array2.length == 0) {
return clone(array1);
}
final byte[] array3 = new byte[array1.length + array2.length];
System.arraycopy(array1, 0, array3, 0, array1.length);
System.arraycopy(array2, 0, array3, array1.length, array2.length);
return array3;
}
public static int lastIndexOf(byte[] array, byte value) {
return lastIndexOf(array, value, 0);
}
public static int lastIndexOf(byte[] array, byte value, int start) {
if (array == null) {
return -1;
}
if (array.length == 0) {
return -1;
}
if (start < 0) {
start = 0;
}
for (int i = array.length - 1; i >= start; --i) {
if (value == array[i]) {
return i;
}
}
return -1;
}
/**
* DANGER Untested
*/
public static int lastIndexOf(byte[] array, byte[] value) {
return lastIndexOf(array, value, 0);
}
/**
* DANGER Untested
*/
public static int lastIndexOf(byte[] array, byte[] value, int start) {
if (array == null || value == null) {
return -1;
}
if (array.length == 0 || value.length == 0) {
return -1;
}
if (start < 0) {
start = 0;
}
loop: for (int i = array.length - value.length + 1; i >= start; --i) {
for (int j = 0; j < value.length; j++) {
if (array[i + j] != value[j]) {
continue loop;
}
}
return i;
}
return -1;
}
/**
* Add given byte to the end of this array.
*/
public static byte[] push(byte[] array, byte element) {
if (array == null) {
return null;
}
final byte[] array2 = new byte[array.length + 1];
System.arraycopy(array, 0, array2, 1, array.length);
array2[0] = element;
return array2;
}
/**
* Byte array based replace.
*/
public static byte[] replace(final byte[] haystack, final byte[] needle, final byte[] replacement) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
int start = 0;
int n = -1;
try {
while ((n = indexOf(haystack, needle, start)) != -1) {
baos.write(Arrays.copyOfRange(haystack, start, n));
baos.write(replacement);
start = n + needle.length;
}
if (start < haystack.length) {
baos.write(Arrays.copyOfRange(haystack, start, haystack.length));
}
} catch (final Exception e) {
// we should never ever get here
throw new RuntimeException(e.getMessage(), e.getCause());
}
return baos.toByteArray();
}
public static byte[] reverse(byte[] array) {
final byte[] array2 = new byte[array.length];
int index = 0;
for (int i = array.length - 1; i >= 0; --i) {
array2[index++] = array[i];
}
return array2;
}
public static byte[] subarray(byte[] array, int start) {
if (array == null) {
return null;
}
return subarray(array, start, array.length);
}
/**
*
*/
public static byte[] subarray(byte[] array, int start, int length) {
if (array == null) {
return null;
}
if (start < 0) {
start = 0;
}
int end = start+length;
if (end > array.length) {
end = array.length;
}
if (length <= 0) {
return new byte[0];
}
final byte[] subarray = new byte[length];
System.arraycopy(array, start, subarray, 0, length);
return subarray;
}
/**
* Equivalent to <code>new byte[] { element, ... }</code>
*
* @param elements
* @return
*/
public static byte[] wrap(byte... elements) {
return elements;
}
}