software.amazon.event.ruler.input.MultiByte Maven / Gradle / Ivy
package software.amazon.event.ruler.input;
import java.util.Arrays;
import static software.amazon.event.ruler.input.DefaultParser.NINE_BYTE;
import static software.amazon.event.ruler.input.DefaultParser.ZERO_BYTE;
/**
* A grouping of multiple bytes. This can be used to represent a character that has a UTF-8 representation requiring
* multiple bytes.
*/
public final class MultiByte {
public static final byte MIN_FIRST_BYTE_FOR_ONE_BYTE_CHAR = (byte) 0x00;
public static final byte MAX_FIRST_BYTE_FOR_ONE_BYTE_CHAR = (byte) 0x7F;
public static final byte MIN_FIRST_BYTE_FOR_TWO_BYTE_CHAR = (byte) 0xC2;
public static final byte MAX_FIRST_BYTE_FOR_TWO_BYTE_CHAR = (byte) 0xDF;
/**
* A continuation byte is a byte that is not the first UTF-8 byte in a multibyte character.
*/
public static final byte MIN_CONTINUATION_BYTE = (byte) 0x80;
public static final byte MAX_CONTINUATION_BYTE = (byte) 0xBF;
public static final byte MAX_NON_FIRST_BYTE = (byte) 0xBF;
private final byte[] bytes;
MultiByte(byte ... bytes) {
if (bytes.length == 0) {
throw new IllegalArgumentException("Must provide at least one byte");
}
this.bytes = bytes;
}
public byte[] getBytes() {
return Arrays.copyOf(bytes, bytes.length);
}
public byte singular() {
if (bytes.length != 1) {
throw new IllegalStateException("Must be a singular byte");
}
return bytes[0];
}
public boolean is(byte ... bytes) {
return Arrays.equals(this.bytes, bytes);
}
public boolean isNumeric() {
return bytes.length == 1 && bytes[0] >= ZERO_BYTE && bytes[0] <= NINE_BYTE;
}
public boolean isLessThan(MultiByte other) {
return isLessThan(other, false);
}
public boolean isLessThanOrEqualTo(MultiByte other) {
return isLessThan(other, true);
}
public boolean isGreaterThan(MultiByte other) {
return !isLessThanOrEqualTo(other);
}
public boolean isGreaterThanOrEqualTo(MultiByte other) {
return !isLessThan(other);
}
private boolean isLessThan(MultiByte other, boolean orEqualTo) {
byte[] otherBytes = other.getBytes();
for (int i = 0; i < bytes.length; i++) {
if (i == otherBytes.length) {
// otherBytes is a prefix of bytes. Thus, bytes is larger than otherBytes.
return false;
}
if (bytes[i] != otherBytes[i]) {
// Most significant differing byte - return if it is less for bytes than otherBytes.
return (0xFF & bytes[i]) < (0xFF & otherBytes[i]);
}
}
// bytes is equal to (return true if orEqualTo) or a prefix of (return true) otherBytes.
return orEqualTo || (0xFF & bytes.length) < (0xFF & otherBytes.length);
}
@Override
public boolean equals(Object o) {
if (o == null || !(o.getClass() == getClass())) {
return false;
}
return Arrays.equals(((MultiByte) o).getBytes(), getBytes());
}
@Override
public int hashCode() {
return Arrays.hashCode(getBytes());
}
@Override
public String toString() {
return Arrays.toString(getBytes());
}
}