ip util functions and its unit test

This commit is contained in:
lion 2025-09-10 22:46:14 +08:00
parent 83fd149c59
commit 697b46bb2e
3 changed files with 142 additions and 5 deletions

View File

@ -0,0 +1,9 @@
package org.lionsoul.ip2region.xdb;
public class InvalidInetAddressException extends Exception {
public InvalidInetAddressException(String str) {
super(str);
}
}

View File

@ -7,18 +7,61 @@
package org.lionsoul.ip2region.xdb;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Util
{
// parse the specified IP address and return its bytes.
// returns: byte[4] for IPv6 and byte[16] for IPv6 and the bytes should be in Big endian order.
public static byte[] parseIP(String ip) throws InvalidInetAddressException {
try {
return InetAddress.getByName(ip).getAddress();
} catch (UnknownHostException e) {
throw new InvalidInetAddressException("invalid ip address `"+ip+"`");
}
}
// print the ip in bytes
public static String ipToString(final byte[] ip) throws InvalidInetAddressException {
if (ip.length != 4 && ip.length != 16) {
throw new InvalidInetAddressException("invalid ip address length `"+ip.length+"`");
}
try {
return InetAddress.getByAddress(ip).getHostAddress();
} catch (UnknownHostException e) {
throw new InvalidInetAddressException("invalid ip address `"+ipArrayString(ip)+"`");
}
}
// implode the byte[] ip with its byte value.
public static String ipArrayString(byte[] ip) {
final StringBuffer sb = new StringBuffer();
sb.append("[");
for (int i = 0; i < ip.length; i++) {
if (i > 0) {
sb.append(',');
}
sb.append((ip[i] & 0xFF));
}
sb.append("]");
return sb.toString();
}
// compare two byte ip
// Returns: -1 if ip1 < ip2, 0 if ip1 == ip2, 1 if ip1 > ip2
public static int ipCompare(byte[] ip1, byte[] ip2) {
for (int i = 0; i < ip1.length; i++) {
if (ip1[i] < ip2[i]) {
// covert the byte to int to sure the uint8 attribute
final int i1 = (int)(ip1[i] & 0xFF);
final int i2 = (int)(ip2[i] & 0xFF);
if (i1 < i2) {
return -1;
}
if (ip1[i] > ip2[i]) {
if (i1 > i2) {
return 1;
}
}
@ -30,10 +73,13 @@ public class Util
final byte[] r = new byte[ip.length];
System.arraycopy(ip, 0, r, 0, ip.length);
for (int i = ip.length - 1; i >= 0; i--) {
r[i]++;
if (r[i] != 0) { // No overflow
final int v = (int)(r[i] & 0xFF);
if (v < 255) { // No overflow
r[i]++;
break;
}
r[i] = 0;
}
return r;
@ -43,10 +89,12 @@ public class Util
final byte[] r = new byte[ip.length];
System.arraycopy(ip, 0, r, 0, ip.length);
for (int i = ip.length - 1; i >= 0; i--) {
if (r[i] != 0) { // No borrow needed
final int v = (int)(r[i] & 0xFF);
if (v > 0) { // No borrow needed
r[i]--;
break;
}
r[i] = (byte) 0xFF; // borrow from the next byte
}

View File

@ -0,0 +1,80 @@
package org.lionsoul.ip2region.xdb;
import java.net.UnknownHostException;
import org.junit.Test;
public class UtilTest {
public static final Log log = Log.getLogger(UtilTest.class).setLevel(Log.DEBUG);
@Test
public void testCheckIP() throws InvalidInetAddressException {
final String[] ips = new String[]{
"192.168.1.102",
"219.133.111.87",
"::",
"3000::",
"::1001:ffff",
"2001:2:0:ffff:ffff:ffff:ffff:ffff",
"::ffff:114.114.114.114"
};
for (String ip : ips) {
final byte[] ipBytes = Util.parseIP(ip);
log.debugf("%s(v=%s) => %s", ip, Util.ipArrayString(ipBytes), Util.ipToString(ipBytes));
}
}
@Test
public void testIpCompare() throws InvalidInetAddressException {
final String[][] ipPairs = new String[][]{
{"1.0.0.0", "1.0.0.1"},
{"192.168.1.101", "192.168.1.90"},
{"219.133.111.87", "114.114.114.114"},
{"2000::", "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"},
{"2001:4:112::", "2001:4:112:ffff:ffff:ffff:ffff:ffff"},
{"ffff::", "2001:4:ffff:ffff:ffff:ffff:ffff:ffff"}
};
for (String[] ips : ipPairs) {
final byte[] ip1 = Util.parseIP(ips[0]);
final byte[] ip2 = Util.parseIP(ips[1]);
log.debugf("compare(%s, %s): %d", ips[0], ips[1], Util.ipCompare(ip1, ip2));
}
}
@Test
public void testIpAddOne() throws InvalidInetAddressException {
final String[] ips = new String[] {
"1.0.0.0",
"192.168.1.255",
"2000::",
"255.255.255.254",
"0.0.0.255",
"0.255.255.255",
"1.1.255.255"
};
for (String ip : ips) {
final byte[] ipBytes = Util.parseIP(ip);
log.debugf("ipAddOne(%s): %s", ip, Util.ipToString(Util.ipAddOne(ipBytes)));
}
}
@Test
public void testIpSubOne() throws InvalidInetAddressException {
final String[] ips = new String[] {
"192.168.1.255",
"1.0.0.1",
"1.0.0.0",
"2.0.0.0",
"2000::",
"ffff::",
"1::1",
};
for (String ip : ips) {
final byte[] ipBytes = Util.parseIP(ip);
log.debugf("ipSubOne(%s): %s", ip, Util.ipToString(Util.ipSubOne(ipBytes)));
}
}
}