inet.ipaddr.ipv4.IPv4AddressNetwork Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ipaddress Show documentation
Show all versions of ipaddress Show documentation
Library for handling IP addresses, both IPv4 and IPv6
/*
* Copyright 2016-2018 Sean C Foley
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* or at
* https://github.com/seancfoley/IPAddress/blob/master/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inet.ipaddr.ipv4;
import java.io.Serializable;
import java.net.Inet4Address;
import java.util.function.BiFunction;
import java.util.function.Function;
import inet.ipaddr.Address.SegmentValueProvider;
import inet.ipaddr.AddressNetwork;
import inet.ipaddr.HostIdentifierString;
import inet.ipaddr.IPAddress.IPVersion;
import inet.ipaddr.IPAddressNetwork;
import inet.ipaddr.IPAddressSection;
import inet.ipaddr.ipv4.IPv4AddressSection.EmbeddedIPv4AddressSection;
/**
* Provides methods and types associated with all IPv4 addresses.
*
* @author scfoley
*
*/
public class IPv4AddressNetwork extends IPAddressNetwork {
private static final long serialVersionUID = 4L;
private static PrefixConfiguration defaultPrefixConfiguration = AddressNetwork.getDefaultPrefixConfiguration();
private static boolean CACHE_SEGMENTS_BY_PREFIX = true;
private static final IPv4AddressSegment EMPTY_SEGMENTS[] = {};
private static final IPv4AddressSection EMPTY_SECTION[] = {};
private static final IPv4Address EMPTY_ADDRESS[] = {};
public static class IPv4AddressCreator extends IPAddressCreator {
private static final long serialVersionUID = 4L;
protected static class Cache implements Serializable {
private static final long serialVersionUID = 1L;
private transient IPv4AddressSegment ZERO_PREFIX_SEGMENT, ALL_RANGE_SEGMENT;
private transient IPv4AddressSegment segmentCache[];
private transient IPv4AddressSegment segmentPrefixCache[][];
private transient IPv4AddressSegment allPrefixedCache[];
void clear() {
segmentCache = null;
allPrefixedCache = null;
segmentPrefixCache = null;
ZERO_PREFIX_SEGMENT = null;
ALL_RANGE_SEGMENT = null;
}
}
Cache cache;
boolean useSegmentCache = true;
public IPv4AddressCreator(IPv4AddressNetwork network) {
super(network);
this.cache = new Cache();
}
protected IPv4AddressCreator(IPv4AddressNetwork network, Cache cache) {
super(network);
this.cache = cache;
}
@Override
public void clearCaches() {
super.clearCaches();
cache.clear();
}
@Override
public void setSegmentCaching(boolean enable) {
useSegmentCache = enable;
}
@Override
public IPv4AddressNetwork getNetwork() {
return (IPv4AddressNetwork) super.getNetwork();
}
@Override
public int getMaxValuePerSegment() {
return IPv4Address.MAX_VALUE_PER_SEGMENT;
}
@Override
protected int getAddressSegmentCount() {
return IPv4Address.SEGMENT_COUNT;
}
@Override
public IPv4AddressSegment[] createSegmentArray(int length) {
if(length == 0) {
return EMPTY_SEGMENTS;
}
return new IPv4AddressSegment[length];
}
@Override
public IPv4AddressSegment createSegment(int value) {
if(useSegmentCache && value >= 0 && value <= IPv4Address.MAX_VALUE_PER_SEGMENT) {
IPv4AddressSegment result, cache[] = this.cache.segmentCache;
if(cache == null) {
this.cache.segmentCache = cache = new IPv4AddressSegment[IPv4Address.MAX_VALUE_PER_SEGMENT + 1];
cache[value] = result = new IPv4AddressSegment(value);
} else {
result = cache[value];
if(result == null) {
cache[value] = result = new IPv4AddressSegment(value);
}
}
return result;
}
return new IPv4AddressSegment(value);
}
@Override
public IPv4AddressSegment createSegment(int value, Integer segmentPrefixLength) {
if(segmentPrefixLength == null) {
return createSegment(value);
}
if(useSegmentCache && value >= 0 && value <= IPv4Address.MAX_VALUE_PER_SEGMENT && segmentPrefixLength >= 0 && segmentPrefixLength <= IPv4Address.BIT_COUNT) {
if(segmentPrefixLength == 0 && getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets()) {
IPv4AddressSegment result = cache.ZERO_PREFIX_SEGMENT;
if(result == null) {
cache.ZERO_PREFIX_SEGMENT = result = new IPv4AddressSegment(0, 0);
}
return result;
}
if(CACHE_SEGMENTS_BY_PREFIX) {
int mask = getNetwork().getSegmentNetworkMask(segmentPrefixLength);
int prefixIndex = segmentPrefixLength;
int valueIndex;
boolean isAllSubnets = getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets();
if(isAllSubnets) {
value &= mask;
valueIndex = value >>> (IPv4Address.BITS_PER_SEGMENT - segmentPrefixLength);
} else {
valueIndex = value;
}
IPv4AddressSegment result, block[], cache[][] = this.cache.segmentPrefixCache;
if(cache == null) {
this.cache.segmentPrefixCache = cache = new IPv4AddressSegment[IPv4Address.BITS_PER_SEGMENT + 1][];
cache[prefixIndex] = block = new IPv4AddressSegment[isAllSubnets ? (1 << prefixIndex) : 256];
block[valueIndex] = result = new IPv4AddressSegment(value, segmentPrefixLength);
} else {
block = cache[prefixIndex];
if(block == null) {
cache[prefixIndex] = block = new IPv4AddressSegment[isAllSubnets ? (1 << prefixIndex) : 256];
block[valueIndex] = result = new IPv4AddressSegment(value, segmentPrefixLength);
} else {
result = block[valueIndex];
if(result == null) {
block[valueIndex] = result = new IPv4AddressSegment(value, segmentPrefixLength);
}
}
}
return result;
}
}
IPv4AddressSegment result = new IPv4AddressSegment(value, segmentPrefixLength);
return result;
}
@Override
public IPv4AddressSegment createSegment(int lower, int upper, Integer segmentPrefixLength) {
if(segmentPrefixLength == null) {
if(lower == upper) {
return createSegment(lower);
}
if(useSegmentCache && lower == 0 && upper == IPv4Address.MAX_VALUE_PER_SEGMENT) {
IPv4AddressSegment result = cache.ALL_RANGE_SEGMENT;
if(result == null) {
cache.ALL_RANGE_SEGMENT = result = new IPv4AddressSegment(0, IPv4Address.MAX_VALUE_PER_SEGMENT, null);
//could optimize:
//contains
//getValueCount
//includesMax
//includesZero
//isBoundedBy
//getSegmentPrefixLength, getDivisionPrefixLength
//removePrefixLength, withoutPrefixLength, removePrefixLength(boolean)
//isMultiple
//isPrefixBlock
//matches(int)
//toNormalizedString()
//getPrefixValueCount
}
return result;
}
} else {
if(lower == upper) {
return createSegment(lower, segmentPrefixLength);
}
if(useSegmentCache && lower >= 0 && lower <= IPv4Address.MAX_VALUE_PER_SEGMENT &&
upper >= 0 && upper <= IPv4Address.MAX_VALUE_PER_SEGMENT &&
segmentPrefixLength >= 0 && segmentPrefixLength <= IPv4Address.BIT_COUNT) {
if(segmentPrefixLength == 0 && getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets()) {
return createSegment(0, cacheBits(0));
}
if(CACHE_SEGMENTS_BY_PREFIX) {
int bitsPerSegment = IPv4Address.BITS_PER_SEGMENT;
if(segmentPrefixLength > bitsPerSegment) {
segmentPrefixLength = bitsPerSegment;
}
if(getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets()) {
int mask = getNetwork().getSegmentNetworkMask(segmentPrefixLength);
lower &= mask;
if((upper & mask) == lower) {
return createSegment(lower, segmentPrefixLength);
}
if(lower == 0 && upper >= mask) {
//cache */26 type segments
int prefixIndex = segmentPrefixLength;
IPv4AddressSegment result, cache[] = this.cache.allPrefixedCache;
if(cache == null) {
this.cache.allPrefixedCache = cache = new IPv4AddressSegment[IPv4Address.BITS_PER_SEGMENT + 1];
cache[prefixIndex] = result = new IPv4AddressSegment(0, IPv4Address.MAX_VALUE_PER_SEGMENT, segmentPrefixLength);
} else {
result = cache[prefixIndex];
if(result == null) {
cache[prefixIndex] = result = new IPv4AddressSegment(0, IPv4Address.MAX_VALUE_PER_SEGMENT, segmentPrefixLength);
}
}
return result;
}
} else {
if(lower == 0 && upper == IPv4Address.MAX_VALUE_PER_SEGMENT) {
//cache */26 type segments
int prefixIndex = segmentPrefixLength;
IPv4AddressSegment result, cache[] = this.cache.allPrefixedCache;
if(cache == null) {
this.cache.allPrefixedCache = cache = new IPv4AddressSegment[IPv4Address.BITS_PER_SEGMENT + 1];
cache[prefixIndex] = result = new IPv4AddressSegment(0, IPv4Address.MAX_VALUE_PER_SEGMENT, segmentPrefixLength);
} else {
result = cache[prefixIndex];
if(result == null) {
cache[prefixIndex] = result = new IPv4AddressSegment(0, IPv4Address.MAX_VALUE_PER_SEGMENT, segmentPrefixLength);
}
}
return result;
}
}
}
}
}
IPv4AddressSegment result = new IPv4AddressSegment(lower, upper, segmentPrefixLength);
return result;
}
@Override
protected IPv4AddressSection[] createSectionArray(int length) {
if(length == 0) {
return EMPTY_SECTION;
}
return new IPv4AddressSection[length];
}
@Override
protected IPv4AddressSection createSectionInternal(IPv4AddressSegment segments[]) {
return new IPv4AddressSection(segments, false);
}
@Override
protected IPv4AddressSection createPrefixedSectionInternal(IPv4AddressSegment segments[], Integer prefix, boolean singleOnly) {
return new IPv4AddressSection(segments, false, prefix, singleOnly);
}
protected IPv4AddressSection createSectionInternal(int value) {
return new IPv4AddressSection(value);
}
protected IPv4AddressSection createSectionInternal(int value, Integer prefix) {
return new IPv4AddressSection(value, prefix);
}
@Override
public IPv4AddressSection createFullSectionInternal(SegmentValueProvider lowerValueProvider, SegmentValueProvider upperValueProvider, Integer prefix) {
return new IPv4AddressSection(lowerValueProvider, upperValueProvider, IPv4Address.SEGMENT_COUNT, prefix);
}
@Override
protected IPv4AddressSection createSectionInternal(byte[] bytes, int segmentCount, Integer prefix, boolean singleOnly) {
return new IPv4AddressSection(bytes, segmentCount, prefix, false, singleOnly);
}
@Override
protected IPv4AddressSection createSectionInternal(IPv4AddressSegment[] segments, int startIndex, boolean extended) {
return new IPv4AddressSection(segments);
}
@Override
public IPv4AddressSection createSection(byte bytes[], int byteStartIndex, int byteEndIndex, Integer prefix) {
return new IPv4AddressSection(bytes, byteStartIndex, byteEndIndex, -1, prefix, true, false);
}
@Override
public IPv4AddressSection createSection(byte bytes[], Integer prefix) {
return new IPv4AddressSection(bytes, prefix);
}
@Override
protected IPv4AddressSection createSection(byte bytes[], int byteStartIndex, int byteEndIndex, int segmentCount, Integer prefix) {
return new IPv4AddressSection(bytes, byteStartIndex, byteEndIndex, segmentCount, prefix);
}
@Override
public IPv4AddressSection createSection(IPv4AddressSegment segments[], Integer networkPrefixLength) {
return new IPv4AddressSection(segments, networkPrefixLength);
}
@Override
public IPv4AddressSection createSection(IPv4AddressSegment segments[]) {
return new IPv4AddressSection(segments);
}
@Override
protected IPv4AddressSection createEmbeddedSectionInternal(IPAddressSection encompassingSection, IPv4AddressSegment[] segments) {
return new EmbeddedIPv4AddressSection(encompassingSection, segments);
}
@Override
protected IPv4Address[] createAddressArray(int length) {
if(length == 0) {
return EMPTY_ADDRESS;
}
return new IPv4Address[length];
}
@Override
protected IPv4Address createAddressInternal(IPv4AddressSegment segments[]) {
return super.createAddressInternal(segments);
}
@Override
protected IPv4Address createAddressInternal(IPv4AddressSection section, CharSequence zone, HostIdentifierString from, IPv4Address lower, IPv4Address upper) {
IPv4Address result = createAddressInternal(section, from);
result.cache(lower, upper);
return result;
}
@Override
protected IPv4Address createAddressInternal(IPv4AddressSection section, CharSequence zone) {
return createAddress(section);
}
@Override
public IPv4Address createAddress(IPv4AddressSection section) {
return new IPv4Address(section);
}
@Override
public IPv4Address createAddress(Inet4Address addr, Integer networkPrefixLength) {
return new IPv4Address(addr, networkPrefixLength);
}
@Override
public IPv4Address createAddress(Inet4Address addr) {
return new IPv4Address(addr);
}
}
public IPv4AddressNetwork() {
super(IPv4Address.class);
}
@Override
public PrefixConfiguration getPrefixConfiguration() {
return defaultPrefixConfiguration;
}
/**
* Sets the default prefix configuration used by this network.
*
* @see #getPrefixConfiguration()
* @see #getDefaultPrefixConfiguration()
* @see PrefixConfiguration
*/
public static void setDefaultPrefixConfiguration(PrefixConfiguration config) {
defaultPrefixConfiguration = config;
}
/**
* Gets the default prefix configuration used by this network type and version.
*
* @see AddressNetwork#getDefaultPrefixConfiguration()
* @see PrefixConfiguration
*/
public static PrefixConfiguration getDefaultPrefixConfiguration() {
return defaultPrefixConfiguration;
}
protected boolean isCompatible(IPv4AddressNetwork other) {
return super.isCompatible(other);
}
@Override
protected BiFunction getSegmentProducer() {
return (address, index) -> address.getSegment(index);
}
@Override
protected Function getSectionProducer() {
return IPv4Address::getSection;
}
@Override
protected IPv4AddressCreator createAddressCreator() {
return new IPv4AddressCreator(this);
}
@Override
protected IPv4Address createLoopback() {
IPv4AddressCreator creator = getAddressCreator();
IPv4AddressSegment zero = creator.createSegment(0);
IPv4AddressSegment segs[] = creator.createSegmentArray(IPv4Address.SEGMENT_COUNT);
segs[0] = creator.createSegment(127);
segs[1] = segs[2] = zero;
segs[3] = creator.createSegment(1);
return creator.createAddressInternal(segs); /* address creation */
}
@Override
public IPv4AddressCreator getAddressCreator() {
return (IPv4AddressCreator) super.getAddressCreator();
}
@Override
public boolean isIPv4() {
return true;
}
@Override
public IPVersion getIPVersion() {
return IPVersion.IPV4;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy