Skip to content

Instantly share code, notes, and snippets.

@zhoulifu
Created July 14, 2019 04:55
Show Gist options
  • Save zhoulifu/8491bc97c26196ae95a8c62d1622ef2a to your computer and use it in GitHub Desktop.
Save zhoulifu/8491bc97c26196ae95a8c62d1622ef2a to your computer and use it in GitHub Desktop.
bytes array based ascii sequence
import java.util.Arrays;
import java.util.Objects;
public class AsciiSequence implements CharSequence {
private static final AsciiSequence EMPTY_STRING =
new AsciiSequence(new byte[0]);
final byte[] value;
final int offset;
final int length;
private int hash = -1;
private String string = null;
public AsciiSequence(byte[] value) {
this(value, 0, true);
}
public AsciiSequence(byte[] value, boolean share) {
this(value, 0, share);
}
public AsciiSequence(byte[] value, int offset, boolean share) {
this(Objects.requireNonNull(value), offset, value.length, share);
}
public AsciiSequence(byte[] value, int offset, int length, boolean share) {
if (isOutOfBounds(offset, length, value.length)) {
throw new IndexOutOfBoundsException("expected: " + "0 <= offset(" + offset + ") <= offset + length(" +
length + ") <= " + "value.length(" + value.length + ')');
}
for (int i = offset; i < (offset + length); i++) {
if (value[i] != (value[i] & 0x7f)) {
throw new IllegalArgumentException(
value[i] + " is not a valid ascii character");
}
}
if (share) {
this.value = value;
this.offset = offset;
} else {
this.value = Arrays.copyOfRange(value, offset, offset + length);
this.offset = 0;
}
this.length = length;
}
private AsciiSequence(byte[] value, int offset, int length) {
this.value = value;
this.offset = offset;
this.length = length;
}
@Override
public int length() {
return length;
}
@Override
public char charAt(int index) {
return (char) byteAt(index);
}
public byte byteAt(int index) {
if (index < 0 || index >= length) {
throw new IndexOutOfBoundsException("index: " + index + " must be in the range [0," + length + ")");
}
return value[index + offset];
}
@Override
public AsciiSequence subSequence(int start, int end) {
return slice(start, end, true);
}
public AsciiSequence slice(int start) {
return slice(start, length(), true);
}
public AsciiSequence slice(int start, int end) {
return slice(start, end, true);
}
public AsciiSequence slice(int start, int end, boolean share) {
if (start == 0 && end == length()) {
return this;
}
if (end == start) {
return EMPTY_STRING;
}
int len = end - start;
if (isOutOfBounds(start, len, length())) {
throw new IndexOutOfBoundsException("expected: 0 <= start(" + start + ") <= end (" + end + ") <= length("
+ length() + ')');
}
return (share) ?
new AsciiSequence(this.value, offset + start, len) :
new AsciiSequence(Arrays.copyOfRange(this.value, offset + start, offset + start + len), 0, len);
}
/**
* @see Arrays#hashCode(byte[])
*/
@Override
public int hashCode() {
if (hash != -1) {
return hash;
}
int result = 1;
for (int i = offset; i <(offset + length) ; i++) {
result = 31 * result + value[i];
}
hash = result;
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null || obj.getClass() != AsciiSequence.class) {
return false;
}
if (this == obj) {
return true;
}
AsciiSequence other = (AsciiSequence) obj;
return length() == other.length() &&
hashCode() == other.hashCode() &&
valueEquals(value, offset, other.value, other.offset, length());
}
@Override
public String toString() {
String cache = string;
if (cache == null) {
cache = _toString();
string = cache;
}
return cache;
}
private String _toString() {
if (length == 0) {
return "";
}
@SuppressWarnings("deprecation")
final String str = new String(value, 0, offset, length);
return str;
}
public static boolean isOutOfBounds(int index, int length, int capacity) {
return (index | length | (index + length) | (capacity - (index + length))) < 0;
}
private static boolean valueEquals(byte[] a1, int offset1, byte[] a2, int offset2, int length) {
if (a1 == a2 && offset1 == offset2) {
return true;
}
for (int i = 0; i < length; i++) {
if (a1[offset1 + i] != a2[offset2 + i]) {
return false;
}
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment