package org.emdev.utils.bytes; import java.io.IOException; import java.io.OutputStream; import java.util.Comparator; import java.util.LinkedList; public class ByteString implements Comparator<ByteString> { private final byte[] value; private final int offset; private final int count; private int hashCode; private String string; public ByteString(final byte[] bytes) { this.value = new byte[bytes.length]; this.offset = 0; this.count = bytes.length; if (count > 0) { System.arraycopy(bytes, 0, this.value, 0, count); } } public ByteString(final byte[] bytes, final int offset, final int count) { this.value = new byte[count]; this.offset = 0; this.count = count; System.arraycopy(bytes, offset, this.value, 0, count); } public ByteString(final ByteString bytes, final int offset, final int count) { this.value = bytes.value; this.offset = bytes.offset + offset; this.count = count; } public boolean isEmpty() { return count == 0; } public int length() { return count; } public int indexOf(final int value) { return indexOf(value, 0); } public int indexOf(final int value, final int start) { for (int i = start; i < count; i++) { if (this.value[i + offset] == value) { return i; } } return -1; } public LinkedList<ByteString> split(final int separator) { final LinkedList<ByteString> list = new LinkedList<ByteString>(); int start = 0; for (int index = indexOf(separator, start); index != -1; index = indexOf(separator, start)) { list.add(new ByteString(this, start, index - start)); start = index + 1; } if (list.isEmpty()) { list.add(this); } else if (start != this.count) { list.add(new ByteString(this, start, this.count - start)); } return list; } public byte[] toBytes() { final byte[] bytes = new byte[count]; System.arraycopy(this.value, this.offset, bytes, 0, count); return bytes; } public void writeTo(final OutputStream out) throws IOException { out.write(this.value, this.offset, this.count); } @Override public int hashCode() { int hash = hashCode; if (hash == 0) { if (count == 0) { return 0; } final int end = count + offset; final byte[] chars = value; for (int i = offset; i < end; ++i) { hash = 31 * hash + chars[i]; } hashCode = hash; } return hash; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj instanceof ByteString) { final ByteString that = (ByteString) obj; if (this.count != that.count) { return false; } if (this.hashCode() != that.hashCode()) { return false; } for (int i = 0; i < count; i++) { if (this.value[i + this.offset] != that.value[i + that.offset]) { return false; } } return true; } return false; } @Override public int compare(final ByteString lhs, final ByteString rhs) { if (lhs == rhs) { return 0; } if (lhs == null && rhs != null) { return -1; } if (lhs != null && rhs == null) { return +1; } int eqres = 0; int mincount = lhs.count; if (lhs.count < rhs.count) { eqres = -1; mincount = lhs.count; } else if (lhs.count > rhs.count) { eqres = 01; mincount = rhs.count; } for (int i = 0; i < mincount; i++) { final byte lb = lhs.value[i + lhs.offset]; final byte rb = rhs.value[i + rhs.offset]; if (lb < rb) { return -1; } else if (lb > rb) { return +1; } } return eqres; } @Override public String toString() { if (string == null) { final StringBuilder buf = new StringBuilder(); for (int i = this.offset, end = this.offset + this.count; i < end; i++) { final byte b = this.value[i]; if (b >= 0 && b < 128) { buf.append((char) b); } else { buf.append("\\x").append(Integer.toHexString(((int) b) & 0xFF)); } } string = buf.toString(); } return string; } }