mirror of https://github.com/apache/lucene.git
LUCENE-7234: Add InetAddressPoint.nextUp/nextDown
This commit is contained in:
parent
2724b99b5c
commit
91fd163112
|
@ -19,6 +19,9 @@ New Features
|
|||
* LUCENE-7069: Add LatLonPoint.nearest, to find nearest N points to a
|
||||
provided query point (Mike McCandless)
|
||||
|
||||
* LUCENE-7234: Added InetAddressPoint.nextDown/nextUp to easily generate range
|
||||
queries with excluded bounds. (Adrien Grand)
|
||||
|
||||
API Changes
|
||||
|
||||
* LUCENE-7184: Refactor LatLonPoint encoding methods to new GeoEncodingUtils
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.lucene.search.PointInSetQuery;
|
|||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
import org.apache.lucene.util.StringHelper;
|
||||
|
||||
/**
|
||||
|
@ -65,6 +66,53 @@ public class InetAddressPoint extends Field {
|
|||
TYPE.freeze();
|
||||
}
|
||||
|
||||
/** The minimum value that an ip address can hold. */
|
||||
public static final InetAddress MIN_VALUE;
|
||||
/** The maximum value that an ip address can hold. */
|
||||
public static final InetAddress MAX_VALUE;
|
||||
static {
|
||||
MIN_VALUE = decode(new byte[BYTES]);
|
||||
byte[] maxValueBytes = new byte[BYTES];
|
||||
Arrays.fill(maxValueBytes, (byte) 0xFF);
|
||||
MAX_VALUE = decode(maxValueBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link InetAddress} that compares immediately greater than
|
||||
* {@code address}.
|
||||
* @throws ArithmeticException if the provided address is the
|
||||
* {@link #MAX_VALUE maximum ip address}
|
||||
*/
|
||||
public static InetAddress nextUp(InetAddress address) {
|
||||
if (address.equals(MAX_VALUE)) {
|
||||
throw new ArithmeticException("Overflow: there is no greater InetAddress than "
|
||||
+ address.getHostAddress());
|
||||
}
|
||||
byte[] delta = new byte[BYTES];
|
||||
delta[BYTES-1] = 1;
|
||||
byte[] nextUpBytes = new byte[InetAddressPoint.BYTES];
|
||||
NumericUtils.add(InetAddressPoint.BYTES, 0, encode(address), delta, nextUpBytes);
|
||||
return decode(nextUpBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link InetAddress} that compares immediately less than
|
||||
* {@code address}.
|
||||
* @throws ArithmeticException if the provided address is the
|
||||
* {@link #MIN_VALUE minimum ip address}
|
||||
*/
|
||||
public static InetAddress nextDown(InetAddress address) {
|
||||
if (address.equals(MIN_VALUE)) {
|
||||
throw new ArithmeticException("Underflow: there is no smaller InetAddress than "
|
||||
+ address.getHostAddress());
|
||||
}
|
||||
byte[] delta = new byte[BYTES];
|
||||
delta[BYTES-1] = 1;
|
||||
byte[] nextDownBytes = new byte[InetAddressPoint.BYTES];
|
||||
NumericUtils.subtract(InetAddressPoint.BYTES, 0, encode(address), delta, nextDownBytes);
|
||||
return decode(nextDownBytes);
|
||||
}
|
||||
|
||||
/** Change the values of this field */
|
||||
public void setInetAddressValue(InetAddress value) {
|
||||
if (value == null) {
|
||||
|
@ -187,6 +235,12 @@ public class InetAddressPoint extends Field {
|
|||
|
||||
/**
|
||||
* Create a range query for network addresses.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting {@code lowerValue = InetAddressPoint.MIN_VALUE} or
|
||||
* {@code upperValue = InetAddressPoint.MAX_VALUE}.
|
||||
* <p> Ranges are inclusive. For exclusive ranges, pass {@code InetAddressPoint#nextUp(lowerValue)}
|
||||
* or {@code InetAddressPoint#nexDown(upperValue)}.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range (inclusive). must not be null.
|
||||
|
|
|
@ -131,4 +131,46 @@ public class TestInetAddressPoint extends LuceneTestCase {
|
|||
InetAddressPoint.newRangeQuery("a", InetAddress.getByName("2001::a000:0"), InetAddress.getByName("2001::afff:ffff")),
|
||||
InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("2001::a6bd:fc80"), 100));
|
||||
}
|
||||
|
||||
public void testNextUp() throws Exception {
|
||||
assertEquals(InetAddress.getByName("::1"),
|
||||
InetAddressPoint.nextUp(InetAddress.getByName("::")));
|
||||
|
||||
assertEquals(InetAddress.getByName("::1:0"),
|
||||
InetAddressPoint.nextUp(InetAddress.getByName("::ffff")));
|
||||
|
||||
assertEquals(InetAddress.getByName("1.2.4.0"),
|
||||
InetAddressPoint.nextUp(InetAddress.getByName("1.2.3.255")));
|
||||
|
||||
assertEquals(InetAddress.getByName("0.0.0.0"),
|
||||
InetAddressPoint.nextUp(InetAddress.getByName("::fffe:ffff:ffff")));
|
||||
|
||||
assertEquals(InetAddress.getByName("::1:0:0:0"),
|
||||
InetAddressPoint.nextUp(InetAddress.getByName("255.255.255.255")));
|
||||
|
||||
ArithmeticException e = expectThrows(ArithmeticException.class,
|
||||
() -> InetAddressPoint.nextUp(InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
|
||||
assertEquals("Overflow: there is no greater InetAddress than ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", e.getMessage());
|
||||
}
|
||||
|
||||
public void testNextDown() throws Exception {
|
||||
assertEquals(InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"),
|
||||
InetAddressPoint.nextDown(InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
|
||||
|
||||
assertEquals(InetAddress.getByName("::ffff"),
|
||||
InetAddressPoint.nextDown(InetAddress.getByName("::1:0")));
|
||||
|
||||
assertEquals(InetAddress.getByName("1.2.3.255"),
|
||||
InetAddressPoint.nextDown(InetAddress.getByName("1.2.4.0")));
|
||||
|
||||
assertEquals(InetAddress.getByName("::fffe:ffff:ffff"),
|
||||
InetAddressPoint.nextDown(InetAddress.getByName("0.0.0.0")));
|
||||
|
||||
assertEquals(InetAddress.getByName("255.255.255.255"),
|
||||
InetAddressPoint.nextDown(InetAddress.getByName("::1:0:0:0")));
|
||||
|
||||
ArithmeticException e = expectThrows(ArithmeticException.class,
|
||||
() -> InetAddressPoint.nextDown(InetAddress.getByName("::")));
|
||||
assertEquals("Underflow: there is no smaller InetAddress than 0:0:0:0:0:0:0:0", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue