Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
inet.ipaddr.ipv4.IPv4AddressSection Maven / Gradle / Ivy
package inet.ipaddr.ipv4;
import java.util.ArrayList;
import java.util.Iterator;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddress.IPVersion;
import inet.ipaddr.IPAddressConverter.DefaultAddressConverter;
import inet.ipaddr.IPAddressSection;
import inet.ipaddr.IPAddressSection.WildcardOptions.Wildcards;
import inet.ipaddr.IPAddressTypeException;
import inet.ipaddr.format.IPAddressDivision;
import inet.ipaddr.format.IPAddressPart;
import inet.ipaddr.format.IPAddressSegmentGrouping;
import inet.ipaddr.format.util.IPAddressPartConfiguredString;
import inet.ipaddr.format.util.IPAddressPartStringCollection;
import inet.ipaddr.format.util.IPAddressPartStringSubCollection;
import inet.ipaddr.ipv4.IPv4AddressNetwork.IPv4AddressCreator;
import inet.ipaddr.ipv4.IPv4AddressSection.IPv4StringCollection.IPv4AddressSectionStringCollection;
import inet.ipaddr.ipv4.IPv4AddressSection.IPv4StringCollection.IPv4StringBuilder;
import inet.ipaddr.ipv6.IPv6Address.IPv6AddressConverter;
import inet.ipaddr.ipv6.IPv6AddressSection.IPv6StringBuilderOptions;
/**
*
* @author sfoley
*
*/
public class IPv4AddressSection extends IPAddressSection {
private static final long serialVersionUID = 1L;
static class IPv4StringCache extends StringCache {
//a set of pre-defined string types
private static final StringOptions fullParams;
private static final StringOptions canonicalParams;
private static final StringOptions normalizedWildcardParams;
private static final StringOptions sqlWildcardParams;
private static final StringOptions octalParams;
private static final StringOptions hexParams;
static final StringOptions reverseDNSParams;
static {
WildcardOptions allWildcards = new WildcardOptions(WildcardOptions.WildcardOption.ALL);
WildcardOptions allSQLWildcards = new WildcardOptions(WildcardOptions.WildcardOption.ALL, new Wildcards(IPAddress.SEGMENT_SQL_WILDCARD_STR, IPAddress.SEGMENT_SQL_SINGLE_WILDCARD_STR));
WildcardOptions wildcardsRangeOnlyNetworkOnly = new WildcardOptions(WildcardOptions.WildcardOption.NETWORK_ONLY, new Wildcards(IPAddress.RANGE_SEPARATOR_STR));
fullParams = new StringOptions.Builder().setExpandedSegments(true).setWildcardOptions(wildcardsRangeOnlyNetworkOnly).toParams();
canonicalParams = new StringOptions.Builder().toParams();
normalizedWildcardParams = new StringOptions.Builder().setWildcardOptions(allWildcards).toParams();
sqlWildcardParams = new StringOptions.Builder().setWildcardOptions(allSQLWildcards).toParams();
octalParams = new StringOptions.Builder().setRadix(IPv4Address.inet_aton_radix.OCTAL.getRadix()).setSegmentStrPrefix(IPv4Address.inet_aton_radix.OCTAL.getSegmentStrPrefix()).toParams();
hexParams = new StringOptions.Builder().setRadix(IPv4Address.inet_aton_radix.HEX.getRadix()).setSegmentStrPrefix(IPv4Address.inet_aton_radix.HEX.getSegmentStrPrefix()).toParams();
reverseDNSParams = new StringOptions.Builder().setWildcardOptions(allWildcards).setReverse(true).setAddressSuffix(".in-addr.arpa").toParams();
}
public String octalString;
public String hexString;
}
transient IPv4StringCache stringCache;
public IPv4AddressSection(IPv4AddressSegment[] segments, Integer networkPrefixLength) {
this(toCIDRSegments(networkPrefixLength, segments, getIPv4SegmentCreator(), IPv4AddressSegment::toNetworkSegment), false);
}
public IPv4AddressSection(IPv4AddressSegment segments[]) {
this(segments, true);
}
IPv4AddressSection(IPv4AddressSegment segments[], boolean cloneSegments) {
super(segments, null, cloneSegments, false);
}
IPv4AddressSection(byte bytes[], Integer prefix, boolean cloneBytes) {
super(toSegments(bytes, IPv4Address.SEGMENT_COUNT, IPv4Address.BYTES_PER_SEGMENT, IPv4Address.BITS_PER_SEGMENT, getIPv4SegmentCreator(), prefix), bytes, false, cloneBytes);
}
public IPv4AddressSection(byte bytes[], Integer prefix) {
this(bytes, prefix, true);
}
public IPv4AddressSection(byte bytes[]) {
this(bytes, null, true);
}
private IPv4AddressSegment[] getLowestOrHighestSegments(boolean lowest) {
return getSingle(this, (IPv4AddressSegment[]) divisions, getAddressCreator(), (i) -> {
IPv4AddressSegment seg = getSegment(i);
return lowest ? seg.getLower() : seg.getUpper();
}, false);
}
@Override
public IPv4AddressSegment[] getSegments() {
return (IPv4AddressSegment[]) divisions.clone();
}
@Override
public IPv4AddressSegment[] getLowerSegments() {
return getLowestOrHighestSegments(true);
}
@Override
public IPv4AddressSegment[] getUpperSegments() {
return getLowestOrHighestSegments(false);
}
private IPv4AddressSection getLowestOrHighestSection(boolean lowest) {
return getSingle(this, () -> {
IPAddressSection result;
if(hasNoSectionCache() || (result = (lowest ? sectionCache.lowerSection : sectionCache.upperSection)) == null) {
IPv4AddressCreator creator = getAddressCreator();
IPv4AddressSegment[] segs = createSingle(this, creator, i -> {
IPv4AddressSegment seg = getSegment(i);
return lowest ? seg.getLower() : seg.getUpper();
});
IPv4AddressSection newSection = creator.createSectionInternal(segs);
if(lowest) {
sectionCache.lowerSection = newSection;
} else {
sectionCache.upperSection = newSection;
}
return newSection;
}
return (IPv4AddressSection) result;
});
}
@Override
public IPv4AddressSection getLowerSection() {
return getLowestOrHighestSection(true);
}
@Override
public IPv4AddressSection getUpperSection() {
return getLowestOrHighestSection(false);
}
@Override
public Iterator sectionIterator() {
return new SectionIterator(this, getAddressCreator(), iterator(true));
}
private Iterator iterator(boolean skipThis) {
return super.iterator(getSegmentCreator(), skipThis, this::getLowerSegments, index -> getSegment(index).iterator());
}
@Override
public Iterator iterator() {
return iterator(false);
}
@Override
protected IPv4AddressCreator getSegmentCreator() {
return getIPv4SegmentCreator();
}
@Override
protected IPv4AddressCreator getAddressCreator() {
return getIPv4SegmentCreator();
}
private static IPv4AddressCreator getIPv4SegmentCreator() {
return IPv4Address.network().getAddressCreator();
}
@Override
public IPv4AddressSegment getSegment(int index) {
return (IPv4AddressSegment) super.getSegment(index);
}
@Override
public int getBitsPerSegment() {
return IPv4Address.BITS_PER_SEGMENT;
}
@Override
public int getBytesPerSegment() {
return IPv4Address.BYTES_PER_SEGMENT;
}
@Override
public boolean isIPv4() {
return true;
}
@Override
public IPVersion getIPVersion() {
return IPVersion.IPV4;
}
@Override
protected boolean isSameGrouping(IPAddressSegmentGrouping other) {
return other instanceof IPv4AddressSection && super.isSameGrouping(other);
}
@Override
public boolean equals(Object o) {
if(o == this) {
return true;
}
if(o instanceof IPv4AddressSection) {
return super.isSameGrouping((IPv4AddressSection) o);
}
return false;
}
@Override
public boolean contains(IPAddressSection other) {
return other.isIPv4() && super.contains(other);
}
@Override
public IPv4AddressSection[] subtract(IPAddressSection other) {
if(!(other instanceof IPv4AddressSection)) {
throw new IPAddressTypeException(this, other, "ipaddress.error.typeMismatch");
}
return subtract(this, (IPv4AddressSection) other, getAddressCreator(), this::getSegment, (section, prefix) -> section.toSubnet(prefix));
}
@Override
public int getByteIndex(Integer networkPrefixLength) {
return getByteIndex(networkPrefixLength, IPv4Address.BYTE_COUNT);
}
@Override
public int getSegmentIndex(Integer networkPrefixLength) {
return getSegmentIndex(networkPrefixLength, IPv4Address.BYTE_COUNT, IPv4Address.BYTES_PER_SEGMENT);
}
@Override
public IPv4AddressNetwork getNetwork() {
return IPv4Address.network();
}
@Override
public IPv4AddressSection toSubnet(int networkPrefixLength) throws IPAddressTypeException {
super.checkSubnet(networkPrefixLength);
if(isPrefixed() && networkPrefixLength >= getNetworkPrefixLength()) {
return this;
}
IPv4Address addressMask = getNetwork().getNetworkMask(networkPrefixLength, false);
IPv4AddressSection mask = addressMask.getNetworkSection(getBitCount(), false);
return getSubnetSegments(this, mask, networkPrefixLength, getAddressCreator(), false, this::getSegment, mask::getSegment);
}
/**
* Creates a subnet address using the given mask.
*/
@Override
public IPv4AddressSection toSubnet(IPAddressSection mask) throws IPAddressTypeException {
return toSubnet(mask, null);
}
/**
* Creates a subnet address using the given mask and prefix length.
* @param networkPrefixLength if non-null, applies the given prefix
*/
@Override
public IPv4AddressSection toSubnet(IPAddressSection mask, Integer networkPrefixLength) throws IPAddressTypeException {
if(!(mask instanceof IPv4AddressSection)) {
throw new IPAddressTypeException(this, mask, "ipaddress.error.typeMismatch");
}
IPv4AddressSection theMask = (IPv4AddressSection) mask;
super.checkSubnet(theMask, networkPrefixLength);
return getSubnetSegments(this, theMask, networkPrefixLength, getAddressCreator(), true, this::getSegment, theMask::getSegment);
}
@Override
public IPv4AddressSection getNetworkSection(int networkPrefixLength) {
return getNetworkSection(networkPrefixLength, true);
}
@Override
public IPv4AddressSection getNetworkSection(int networkPrefixLength, boolean withPrefixLength) {
int cidrSegmentCount = getNetworkSegmentCount(networkPrefixLength);
return getNetworkSegments(this, networkPrefixLength, cidrSegmentCount, withPrefixLength, getAddressCreator(), (i, prefix) -> getSegment(i).toNetworkSegment(prefix, withPrefixLength));
}
@Override
public IPv4AddressSection getHostSection(int networkPrefixLength) {
int cidrSegmentCount = getHostSegmentCount(networkPrefixLength);
return getHostSegments(this, networkPrefixLength, cidrSegmentCount, getAddressCreator(), (i, prefix) -> getSegment(i).toHostSegment(prefix));
}
@Override
protected boolean hasNoStringCache() {
if(stringCache == null) {
synchronized(this) {
if(stringCache == null) {
stringCache = new IPv4StringCache();
return true;
}
}
}
return false;
}
@Override
protected StringCache getStringCache() {
return stringCache;
}
/**
* This produces a canonical string.
*/
@Override
public String toCanonicalString() {
String result;
if(hasNoStringCache() || (result = stringCache.canonicalString) == null) {
stringCache.canonicalString = result = toNormalizedString(IPv4StringCache.canonicalParams);
}
return result;
}
/**
* This produces a string with no compressed segments and all segments of full length,
* which is 3 characters for IPv4 segments.
*/
@Override
public String toFullString() {
String result;
if(hasNoStringCache() || (result = stringCache.fullString) == null) {
stringCache.fullString = result = toNormalizedString(IPv4StringCache.fullParams);
}
return result;
}
/**
* The shortest string for IPv4 addresses is the same as the canonical string.
*/
@Override
public String toCompressedString() {
return toCanonicalString();
}
/**
* The normalized string returned by this method is consistent with java.net.Inet4Address,
* and is the same as the canonical string.
*/
@Override
public String toNormalizedString() {
return toCanonicalString();
}
@Override
protected void cacheNormalizedString(String str) {
if(hasNoStringCache() || stringCache.canonicalString == null) {
stringCache.canonicalString = str;
}
}
@Override
public String toCompressedWildcardString() {
return toNormalizedWildcardString();
}
@Override
public String toSubnetString() {
return toNormalizedWildcardString();
}
@Override
public String toNetworkPrefixLengthString() {
return toCanonicalString();
}
public String toInetAtonString(IPv4Address.inet_aton_radix radix) {
String result;
if(radix == IPv4Address.inet_aton_radix.OCTAL) {
if(hasNoStringCache() || (result = stringCache.octalString) == null) {
stringCache.octalString = result = toNormalizedString(IPv4StringCache.octalParams);
}
} else if(radix == IPv4Address.inet_aton_radix.HEX) {
if(hasNoStringCache() || (result = stringCache.hexString) == null) {
stringCache.hexString = result = toNormalizedString(IPv4StringCache.hexParams);
}
} else {
result = toCanonicalString();
}
return result;
}
public String toInetAtonString(IPv4Address.inet_aton_radix radix, int joinedCount) {
if(joinedCount <= 0) {
return toInetAtonString(radix);
}
StringOptions stringParams;
if(radix == IPv4Address.inet_aton_radix.OCTAL) {
stringParams = IPv4StringCache.octalParams;
} else if(radix == IPv4Address.inet_aton_radix.HEX) {
stringParams = IPv4StringCache.hexParams;
} else {
stringParams = IPv4StringCache.canonicalParams;
}
return toNormalizedString(stringParams, joinedCount);
}
@Override
public String toNormalizedWildcardString() {
String result;
if(hasNoStringCache() || (result = stringCache.normalizedWildcardString) == null) {
stringCache.normalizedWildcardString = result = toNormalizedString(IPv4StringCache.normalizedWildcardParams);
}
return result;
}
@Override
public String toCanonicalWildcardString() {
return toNormalizedWildcardString();
}
@Override
public String toSQLWildcardString() {
String result;
if(hasNoStringCache() || (result = stringCache.sqlWildcardString) == null) {
stringCache.sqlWildcardString = result = toNormalizedString(IPv4StringCache.sqlWildcardParams);
}
return result;
}
public String toNormalizedString(StringOptions stringParams, int joinCount) {
if(joinCount <= 0) {
return toNormalizedString(stringParams);
}
int thisCount = getSegmentCount();
if(thisCount <= 1) {
return toNormalizedString(stringParams);
}
IPAddressPart equivalentPart = toJoinedSegments(joinCount);
return toNormalizedString(stringParams, equivalentPart);
}
public IPAddressSegmentGrouping toJoinedSegments(int joinCount) {
int thisCount = getSegmentCount();
if(joinCount <= 0 || thisCount <=1) {
return this;
}
int totalCount;
if(joinCount >= thisCount) {
joinCount = thisCount - 1;
totalCount = 1;
} else {
totalCount = thisCount - joinCount;
}
int notJoinedCount = totalCount - 1;
IPAddressDivision segs[] = new IPAddressDivision[totalCount];
int i = 0;
for(; i < notJoinedCount; i++) {
segs[i] = getDivision(i);
}
IPv4JoinedSegments joinedSegment = joinSegments(joinCount);
segs[notJoinedCount] = joinedSegment;
IPAddressSegmentGrouping equivalentPart = new IPAddressSegmentGrouping(segs);
return equivalentPart;
}
private IPv4JoinedSegments joinSegments(int joinCount) {
long lower = 0, upper = 0;
int networkPrefixLength = 0;
Integer prefix = null;
int firstSegIndex = 0;
IPv4AddressSegment firstRange = null;
int firstJoinedIndex = getSegmentCount() - 1 - joinCount;
for(int j = 0; j <= joinCount; j++) {
IPv4AddressSegment thisSeg = getSegment(firstJoinedIndex + j);
if(firstRange != null) {
if(!thisSeg.isFullRange()) {
throw new IPAddressTypeException(firstRange, firstSegIndex, thisSeg, firstJoinedIndex + j, "ipaddress.error.segmentMismatch");
}
} else if(thisSeg.isMultiple()) {
firstSegIndex = firstJoinedIndex + j;
firstRange = thisSeg;
}
lower = lower << IPv4Address.BITS_PER_SEGMENT | thisSeg.getLowerSegmentValue();
upper = upper << IPv4Address.BITS_PER_SEGMENT | thisSeg.getUpperSegmentValue();
if(prefix == null) {
Integer thisSegPrefix = thisSeg.getSegmentPrefixLength();
if(thisSegPrefix != null) {
prefix = networkPrefixLength + thisSegPrefix;
} else {
networkPrefixLength += thisSeg.getBitCount();
}
}
}
IPv4JoinedSegments joinedSegment = new IPv4JoinedSegments(joinCount, lower, upper, prefix);
return joinedSegment;
}
@Override
public IPAddressPartStringCollection toAllStringCollection() {
return toStringCollection(IPv4StringBuilderOptions.ALL_OPTS);
}
@Override
public IPAddressPartStringCollection toStandardStringCollection() {
return toStringCollection(IPv4StringBuilderOptions.STANDARD_OPTS);
}
@Override
public IPAddressPartStringCollection toDatabaseSearchStringCollection() {
return toStringCollection(IPv4StringBuilderOptions.DATABASE_SEARCH_OPTS);
}
@Override
public IPAddressPartStringCollection toStringCollection(IPStringBuilderOptions opts) {
return toStringCollection(IPv4StringBuilderOptions.from(opts));
}
public IPAddressPartStringCollection toStringCollection(IPv4StringBuilderOptions opts) {
IPv4SectionStringCollection collection = new IPv4SectionStringCollection();
IPAddressPart parts[] = getParts(opts);
for(IPAddressPart part : parts) {
IPv4StringBuilder builder = new IPv4StringBuilder(part, opts, new IPv4AddressSectionStringCollection(part));
IPv4AddressSectionStringCollection subCollection = builder.getVariations();
collection.add(subCollection);
}
return collection;
}
@Override
public IPAddressPart[] getParts(IPStringBuilderOptions options) {
return getParts(IPv4StringBuilderOptions.from(options));
}
public IPAddressPart[] getParts(IPv4StringBuilderOptions options) {
if(!options.includesAny(IPv4StringBuilderOptions.ALL_JOINS)) {
return super.getParts(options);
}
ArrayList parts = new ArrayList<>(IPv4Address.SEGMENT_COUNT);
if(options.includes(IPStringBuilderOptions.BASIC)) {
parts.add(this);
}
boolean joined[] = new boolean[IPv4Address.SEGMENT_COUNT];
int segmentCount = getSegmentCount();
joined[Math.max(3, segmentCount - 1)] = options.includes(IPv4StringBuilderOptions.JOIN_ALL);
joined[Math.max(2, Math.min(2, segmentCount - 1))] |= options.includes(IPv4StringBuilderOptions.JOIN_TWO);
joined[Math.max(1, Math.min(1, segmentCount - 1))] |= options.includes(IPv4StringBuilderOptions.JOIN_ONE);
for(int i = 1; i < joined.length; i++) {
if(joined[i]) {
parts.add(toJoinedSegments(i));
}
}
return parts.toArray(new IPAddressPart[parts.size()]);
}
static class IPv4SectionStringCollection extends IPAddressPartStringCollection {
@Override
protected void add(IPAddressPartStringSubCollection> collection) {
super.add(collection);
}
@Override
protected void addAll(IPAddressPartStringCollection collections) {
super.addAll(collections);
}
}
public static class IPv4StringBuilderOptions extends IPStringBuilderOptions {
public static final int JOIN_ALL = 0x2;
public static final int JOIN_TWO = 0x4;
public static final int JOIN_ONE = 0x8;
public static final int ALL_JOINS = JOIN_ALL | JOIN_TWO | JOIN_ONE;
public static final int IPV6_CONVERSIONS = 0x10000;
//right now we do not do mixing of octal and/or hex and/or decimal which could create another 81 = 3^4 combos with 4 segments
public static final int OCTAL = 0x100;
public static final int HEX = 0x200;
public final IPv6StringBuilderOptions ipv6ConverterOptions;
public final IPv6AddressConverter converter;
public static final IPv4StringBuilderOptions STANDARD_OPTS = new IPv4StringBuilderOptions(IPStringBuilderOptions.BASIC | IPStringBuilderOptions.LEADING_ZEROS_FULL_ALL_SEGMENTS);
public static final IPv4StringBuilderOptions DATABASE_SEARCH_OPTS = new IPv4StringBuilderOptions();
public static final IPv4StringBuilderOptions ALL_OPTS = new IPv4StringBuilderOptions(
IPStringBuilderOptions.BASIC |
IPv4StringBuilderOptions.JOIN_ALL |
IPv4StringBuilderOptions.JOIN_TWO |
IPv4StringBuilderOptions.JOIN_ONE |
IPv4StringBuilderOptions.HEX |
IPv4StringBuilderOptions.OCTAL |
IPv4StringBuilderOptions.IPV6_CONVERSIONS |
IPStringBuilderOptions.LEADING_ZEROS_FULL_SOME_SEGMENTS,
null,
new IPv6StringBuilderOptions(
IPStringBuilderOptions.BASIC |
IPv6StringBuilderOptions.MIXED |
IPv6StringBuilderOptions.UPPERCASE |
IPv6StringBuilderOptions.COMPRESSION_ALL_FULL |
IPStringBuilderOptions.LEADING_ZEROS_FULL_SOME_SEGMENTS));
public IPv4StringBuilderOptions() {
this.ipv6ConverterOptions = null;
this.converter = null;
}
public IPv4StringBuilderOptions(int options) {
this(options, null, null);
}
public IPv4StringBuilderOptions(int options, IPv6AddressConverter ipv6AddressConverter, IPv6StringBuilderOptions ipv6ConverterOptions) {
super(options | (ipv6ConverterOptions == null ? 0 : IPV6_CONVERSIONS));
if(includes(IPV6_CONVERSIONS)) {
if(ipv6ConverterOptions == null) {
ipv6ConverterOptions = new IPv6StringBuilderOptions(
IPStringBuilderOptions.BASIC |
IPv6StringBuilderOptions.UPPERCASE |
IPv6StringBuilderOptions.COMPRESSION_ALL_FULL |
IPv6StringBuilderOptions.LEADING_ZEROS_FULL_ALL_SEGMENTS |
IPv6StringBuilderOptions.MIXED);
}
if(ipv6AddressConverter == null) {
ipv6AddressConverter = IPAddress.addressConverter;
if(ipv6AddressConverter == null) {
ipv6AddressConverter = new DefaultAddressConverter();
}
}
}
this.ipv6ConverterOptions = ipv6ConverterOptions;
this.converter = ipv6AddressConverter;
}
public static IPv4StringBuilderOptions from(IPStringBuilderOptions opts) {
if(opts instanceof IPv4StringBuilderOptions) {
return (IPv4StringBuilderOptions) opts;
}
return new IPv4StringBuilderOptions(opts.options & ~(ALL_JOINS | IPV6_CONVERSIONS | OCTAL | HEX));
}
}
static class IPv4StringCollection extends IPAddressPartStringCollection {
@Override
protected void addAll(IPAddressPartStringCollection collections) {
super.addAll(collections);
}
static class IPv4AddressSectionStringCollection extends IPAddressPartStringSubCollection> {
IPv4AddressSectionStringCollection(IPAddressPart addr) {
super(addr);
}
@Override
public Iterator> iterator() {
return new IPAddressConfigurableStringIterator() {
@Override
public IPAddressPartConfiguredString next() {
return new IPAddressPartConfiguredString(part, iterator.next());
}
};
}
}
/**
* Each IPv4StringParams instance has settings to write exactly one IPv4 address section string.
* Using this class allows us to avoid referencing StringParams everywhere,
* but in reality this class has no functionality of its own.
*
* @author sfoley
*
*/
private static class IPv4StringParams extends StringParams {
IPv4StringParams(int radix) {
super(radix, IPv4Address.SEGMENT_SEPARATOR, false);
}
@Override
public IPv4StringParams clone() {
return (IPv4StringParams) super.clone();
}
}
/**
* Capable of building any and all possible representations of IPv4 addresses.
* Not all such representations are necessarily something you might consider valid.
* For example: 001.02.3.04
* This string has the number '2' and '4' expanded partially to 02 (a partial expansion), rather than left as is, or expanded to the full 3 chars 002.
* The number '1' is fully expanded to 3 characters.
*
* With the default settings of this class, a single address can have 16 variations. If partial expansions are allowed, there are many more.
*
* @author sfoley
*/
static class IPv4StringBuilder
extends AddressPartStringBuilder, IPv4AddressSectionStringCollection, IPv4StringBuilderOptions> {
private IPv4StringBuilder(IPAddressPart address, IPv4StringBuilderOptions options, IPv4AddressSectionStringCollection collection) {
super(address, options, collection);
}
@Override
public void addAllVariations() {
ArrayList allParams = new ArrayList();
ArrayList radices = new ArrayList();
radices.add(IPv4Address.DEFAULT_TEXTUAL_RADIX);
if(options.includes(IPv4StringBuilderOptions.HEX)) {
radices.add(16);
}
boolean hasDecimalOctalDups = false;
if(options.includes(IPv4StringBuilderOptions.OCTAL)) {
radices.add(8);
//We need to consider when octal intersects with a leading zero config. 01 as octal vs 01 as a decimal with leading zero
//Or 001 as octal with a single leading zero and 001 as decimal with two leading zeros.
//However, keep in mind this is only true when the segment value is <= 8, otherwise the segment value is different in octal.
//So if the segment value is <=8 (or both values of a range are <=8) and we are doing both decimal and octal and we are doing partial expansions,
//then we cannot have repeats. In such cases, each octal expansion of size x is same as decimal expansion of size x + 1 (where x = 0 or 1)
//But the full string is only a repeat if the whole thing is same in decimal as octal. Only then will we see dups.
//So, we skip if we are (a) doing both octal and decimal and (b) all segments are <=8 and
//case 1: for the octal: (c) Every segment is either no expansion or expansion of size 1
//case 2: for the decimal: (c) Every segment is an expansion of size 1 or 2 (ie 2 is full)
//Here we are checking for cases (a) and (b). (c) we check below.
hasDecimalOctalDups = IPv4Address.inet_aton_radix.OCTAL.getSegmentStrPrefix().equals("0") &&
IPAddressSection.isDecimalSameAsOctal(false, addressSection);
}
for(int radix : radices) {
ArrayList radixParams = new ArrayList();
IPv4StringParams stringParams = new IPv4StringParams(radix);
radixParams.add(stringParams);
switch(radix) {
case 8:
stringParams.setSegmentStrPrefix(IPv4Address.inet_aton_radix.OCTAL.getSegmentStrPrefix());
break;
case 16:
stringParams.setSegmentStrPrefix(IPv4Address.inet_aton_radix.HEX.getSegmentStrPrefix());
break;
}
if(options.includes(IPStringBuilderOptions.LEADING_ZEROS_FULL_SOME_SEGMENTS)) {
int expandables[] = getExpandableSegments(radix);
for(int i = 0; i < addressSection.getDivisionCount(); i++) {
int expansionLength = expandables[i];
int len = radixParams.size();
while(expansionLength > 0) {
for(int j = 0; j < len; j++) {
IPv4StringParams clone = radixParams.get(j);
if(hasDecimalOctalDups && radix == 10) {
//See above for explanation.
//we know already expansionLength == 1 || expansionLength == 2 for the current segment
//Here we check the others
boolean isDup = true;
for(int k = 0; k < addressSection.getDivisionCount(); k++) {
if(k != i) {
int length = clone.getExpandedSegmentLength(k);
if(length == 0) {//length is not either 1 or 2
isDup = false;
break;
}
}
}
if(isDup) {
//this decimal string is a duplicate of an octal string, so we skip it
continue;
}
}
clone = clone.clone();
clone.expandSegment(i, expansionLength, addressSection.getDivisionCount());
radixParams.add(clone);
}
if(!options.includes(IPStringBuilderOptions.LEADING_ZEROS_PARTIAL_SOME_SEGMENTS)) {
break;
}
expansionLength--;
}
}
} else if(options.includes(IPStringBuilderOptions.LEADING_ZEROS_FULL_ALL_SEGMENTS)) {
boolean allExpandable = isExpandable(radix);
if(allExpandable) {
IPv4StringParams expandParams = new IPv4StringParams(IPv4Address.DEFAULT_TEXTUAL_RADIX);
expandParams.expandSegments(true);
radixParams.add(expandParams);
}
}
allParams.addAll(radixParams);
}
for(int i=0; i