
software.amazon.event.ruler.Range Maven / Gradle / Ivy
package software.amazon.event.ruler;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
/**
* Represents a range of numeric values to match against.
* "Numeric" means that the character repertoire is "digits"; initially, either 0-9 or 0-9a-f. In the current
* implementation, the number of digits in the top and bottom of the range is the same.
*/
public final class Range extends Patterns {
/**
* Bottom and top of the range. openBottom true means we're looking for > bottom, false means >=
* Similarly, openTop true means we're looking for < top, false means <= top.
*/
final byte[] bottom;
final boolean openBottom;
final byte[] top;
final boolean openTop;
final boolean isCIDR;
private static final int HEX_DIGIT_A_DECIMAL_VALUE = 10;
private Range(final double bottom, final boolean openBottom, final double top, final boolean openTop) {
super(MatchType.NUMERIC_RANGE);
if (bottom >= top) {
throw new IllegalArgumentException("Bottom must be less than top");
}
this.bottom = ComparableNumber.generate(bottom).getBytes(StandardCharsets.UTF_8);
this.openBottom = openBottom;
this.top = ComparableNumber.generate(top).getBytes(StandardCharsets.UTF_8);
this.openTop = openTop;
isCIDR = false;
}
Range(final byte[] bottom, final boolean openBottom, final byte[] top, final boolean openTop, final boolean isCIDR) {
super(MatchType.NUMERIC_RANGE);
this.bottom = bottom;
this.top = top;
this.openBottom = openBottom;
this.openTop = openTop;
this.isCIDR = isCIDR;
}
private Range(Range range) {
super(MatchType.NUMERIC_RANGE);
this.bottom = range.bottom.clone();
this.openBottom = range.openBottom;
this.top = range.top.clone();
this.openTop = range.openTop;
this.isCIDR = range.isCIDR;
}
public static Range lessThan(final double val) {
return new Range(-Constants.FIVE_BILLION, false, val, true);
}
public static Range lessThanOrEqualTo(final double val) {
return new Range(-Constants.FIVE_BILLION, false, val, false);
}
public static Range greaterThan(final double val) {
return new Range(val, true, Constants.FIVE_BILLION, false);
}
public static Range greaterThanOrEqualTo(final double val) {
return new Range(val, false, Constants.FIVE_BILLION, false);
}
public static Range between(final double bottom, final boolean openBottom, final double top, final boolean openTop) {
return new Range(bottom, openBottom, top, openTop);
}
private static Range deepCopy(final Range range) {
return new Range(range);
}
/**
* This is necessitated by the fact that we do range comparisons of numbers, fixed-length strings of digits, and
* in the case where the numbers represent IP addresses, they are hex digits. So we need to be able to say
* "for all digits between '3' and 'C'". This is for that.
*
* @param first Start one digit higher than this, for example '4'
* @param last Stop one digit lower than this, for example 'B'
* @return The digit list, for example [ '4', '5', '6', '7', '8', '9', '9', 'A' ] (with 'B' for longDigitSequence)
*/
static byte[] digitSequence(byte first, byte last, boolean includeFirst, boolean includeLast) {
assert first <= last && first <= 'F' && first >= '0' && last <= 'F';
assert !((first == last) && !includeFirst && !includeLast);
int i = getHexByteIndex(first);
int j = getHexByteIndex(last);
if ((!includeFirst) && (i < (Constants.HEX_DIGITS.length - 1))) {
i++;
}
if (includeLast) {
j++;
}
byte[] bytes = new byte[j - i];
System.arraycopy(Constants.HEX_DIGITS, i, bytes, 0, j - i);
return bytes;
}
private static int getHexByteIndex(byte value) {
// ['0'-'9'] maps to [0-9] indexes
if (value >= '0' && value <= '9') {
return value - '0';
}
// ['A'-'F'] maps to [10-15] indexes
return (value - 'A') + HEX_DIGIT_A_DECIMAL_VALUE;
}
@Override
public Object clone() {
super.clone();
return Range.deepCopy(this);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || !o.getClass().equals(getClass())) {
return false;
}
if (!super.equals(o)) {
return false;
}
Range range = (Range) o;
return openBottom == range.openBottom &&
openTop == range.openTop &&
Arrays.equals(bottom, range.bottom) &&
Arrays.equals(top, range.top);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + Arrays.hashCode(bottom);
result = 31 * result + Boolean.hashCode(openBottom);
result = 31 * result + Arrays.hashCode(top);
result = 31 * result + Boolean.hashCode(openTop);
return result;
}
public String toString() {
return (new String(bottom, StandardCharsets.UTF_8)) + '/' + (new String(top, StandardCharsets.UTF_8))
+ ':' + openBottom + '/' + openTop + " (" + super.toString() + ")";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy