Closed maytasm closed 2 years ago
Yes, I think a combination of code and using the right wildcards can do this.
The result does not need to be a set of IPAddressSeqRange, they can all be represented as IPAddress instances.
test("192.168.");
test("192.1");
test("2");
test("3");
test("3.");
test("3.3");
test("2:");
test("2::");
test("2::2");
test("2:2");
test("::");
test("::2");
test("1:2:3:4:5::7");
test("1.2.3.4");
test("1.2.3.");
test("1.2.3");
static void test(String str) throws AddressStringException {
System.out.print("Original string is: ");
System.out.println(str);
IPAddress result[] = extrapolate(str);
System.out.print("Subnets are: ");
print(result);
System.out.println();
}
static IPAddress[] extrapolate(String str) throws AddressStringException {
String strs[] = extrapolateStrings(str);
System.out.print("Address strings are: ");
print(strs);
IPAddress addresses[] = new IPAddress[strs.length];
int i = 0;
for(String addrStr : strs) {
addresses[i++] = new IPAddressString(addrStr).getAddress();
}
return addresses;
}
static String[] extrapolateStrings(String str) throws AddressStringException {
int ipv6Index = str.lastIndexOf(IPv6Address.SEGMENT_SEPARATOR);
String strs[];
if(ipv6Index == -1) {
int ipv4Index = str.lastIndexOf(IPv4Address.SEGMENT_SEPARATOR);
if(ipv4Index == -1) {
for(int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
return extrapolate(str, -1, 1, false);
}
}
String ipv4Strs[] = extrapolate(str, -1, 1, true);
String ipv6Strs[] = extrapolate(str, -1, 1, false);
strs = new String[ipv4Strs.length + ipv6Strs.length];
System.arraycopy(ipv4Strs, 0, strs, 0, ipv4Strs.length);
System.arraycopy(ipv6Strs, 0, strs, ipv4Strs.length, ipv6Strs.length);
} else {
int segCount = 2;
for(int i = ipv4Index; i >= 0; segCount++) {
i = str.substring(0, i).lastIndexOf(IPv4Address.SEGMENT_SEPARATOR);
if(i == -1) {
break;
}
}
strs = extrapolate(str, ipv4Index, segCount, true);
}
} else {
if(ipv6Index == 0) {
throw new AddressStringException(str);
}
int segCount = 2;
for(int i = ipv6Index; i >= 0; segCount++) {
i = str.substring(0, i).lastIndexOf(IPv6Address.SEGMENT_SEPARATOR);
if(i == -1) {
break;
}
}
strs = extrapolate(str, ipv6Index, segCount, false);
}
return strs;
}
static String singleDigitWildcards = "" + IPAddress.SEGMENT_SQL_SINGLE_WILDCARD +
IPAddress.SEGMENT_SQL_SINGLE_WILDCARD +
IPAddress.SEGMENT_SQL_SINGLE_WILDCARD;
static String[] extrapolate(String str, int lastSeparatorIndex, int totalSegs, boolean isIPv4) {
int maxSegSize = isIPv4 ? 3 : 4;
int maxSegCount = isIPv4 ? IPv4Address.SEGMENT_COUNT : IPv6Address.SEGMENT_COUNT;
char sep = isIPv4 ? IPv4Address.SEGMENT_SEPARATOR : IPv6Address.SEGMENT_SEPARATOR;
int lastSegSize = str.length() - lastSeparatorIndex - 1;
if(lastSegSize == 0) {
return new String[] {str + IPAddress.SEGMENT_WILDCARD};
}
ArrayList<String> strs = new ArrayList<String>(4);
char firstChar = str.charAt(lastSeparatorIndex + 1);
String moreSegs = "" + sep + IPAddress.SEGMENT_WILDCARD;
for(int segCharCount = lastSegSize; segCharCount <= maxSegSize; segCharCount++) {
if(isIPv4 && segCharCount == maxSegSize && firstChar != '1' && firstChar != '2' && firstChar != '0'){
break;
}
String segEnd = singleDigitWildcards.substring(0, segCharCount - lastSegSize);
String addr;
if(totalSegs < maxSegCount) {
addr = str + segEnd + moreSegs;
} else {
addr = str + segEnd;
}
strs.add(addr);
}
return strs.toArray(new String[strs.size()]);
}
static void print(Object addresses[]) {
System.out.println(Arrays.asList(addresses));
}
Output:
Original string is: 192.168.
Address strings are: [192.168.*]
Subnets are: [192.168.*.*]
Original string is: 192.1
Address strings are: [192.1.*, 192.1_.*, 192.1__.*]
Subnets are: [192.1.*.*, 192.10-19.*.*, 192.100-199.*.*]
Original string is: 2
Address strings are: [2.*, 2_.*, 2__.*, 2:*, 2_:*, 2__:*, 2___:*]
Subnets are: [2.*.*.*, 20-29.*.*.*, 200-255.*.*.*, 2:*:*:*:*:*:*:*, 20-2f:*:*:*:*:*:*:*, 200-2ff:*:*:*:*:*:*:*, 2000-2fff:*:*:*:*:*:*:*]
Original string is: 3
Address strings are: [3.*, 3_.*, 3:*, 3_:*, 3__:*, 3___:*]
Subnets are: [3.*.*.*, 30-39.*.*.*, 3:*:*:*:*:*:*:*, 30-3f:*:*:*:*:*:*:*, 300-3ff:*:*:*:*:*:*:*, 3000-3fff:*:*:*:*:*:*:*]
Original string is: 3.
Address strings are: [3.*]
Subnets are: [3.*.*.*]
Original string is: 3.3
Address strings are: [3.3.*, 3.3_.*]
Subnets are: [3.3.*.*, 3.30-39.*.*]
Original string is: 2:
Address strings are: [2:*]
Subnets are: [2:*:*:*:*:*:*:*]
Original string is: 2::
Address strings are: [2::*]
Subnets are: [2::*]
Original string is: 2::2
Address strings are: [2::2:*, 2::2_:*, 2::2__:*, 2::2___:*]
Subnets are: [2::2:*, 2::20-2f:*, 2::200-2ff:*, 2::2000-2fff:*]
Original string is: 2:2
Address strings are: [2:2:*, 2:2_:*, 2:2__:*, 2:2___:*]
Subnets are: [2:2:*:*:*:*:*:*, 2:20-2f:*:*:*:*:*:*, 2:200-2ff:*:*:*:*:*:*, 2:2000-2fff:*:*:*:*:*:*]
Original string is: ::
Address strings are: [::*]
Subnets are: [::*]
Original string is: ::2
Address strings are: [::2:*, ::2_:*, ::2__:*, ::2___:*]
Subnets are: [::2:*, ::20-2f:*, ::200-2ff:*, ::2000-2fff:*]
Original string is: 1:2:3:4:5::7
Address strings are: [1:2:3:4:5::7:*, 1:2:3:4:5::7_:*, 1:2:3:4:5::7__:*, 1:2:3:4:5::7___:*]
Subnets are: [1:2:3:4:5:0:7:*, 1:2:3:4:5:0:70-7f:*, 1:2:3:4:5:0:700-7ff:*, 1:2:3:4:5:0:7000-7fff:*]
Original string is: 1.2.3.4
Address strings are: [1.2.3.4, 1.2.3.4_]
Subnets are: [1.2.3.4, 1.2.3.40-49]
Original string is: 1.2.3.
Address strings are: [1.2.3.*]
Subnets are: [1.2.3.*]
Original string is: 1.2.3
Address strings are: [1.2.3.*, 1.2.3_.*]
Subnets are: [1.2.3.*, 1.2.30-39.*]
Is there any feature to support extrapolating partial IP string into a Set of IPAddressSeqRange? For example,
192.168.
-> this will be a set containing192.168.*
192.1
-> this will be a set containing192.1.*
,192.10-19.*
,192.1.00-199.*
2
-> this will be a set containing2.*
,20-29.*
,200-255.*
,2:*
,20-2F.*
,200-2FF.*
,2000-2FFF.*