
inet.ipaddr.ipv4.IPv4AddressSegment Maven / Gradle / Ivy
/*
* 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.util.Iterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import inet.ipaddr.Address;
import inet.ipaddr.AddressNetwork.AddressSegmentCreator;
import inet.ipaddr.AddressSegment;
import inet.ipaddr.AddressValueException;
import inet.ipaddr.IPAddress.IPVersion;
import inet.ipaddr.IPAddressSegment;
import inet.ipaddr.IncompatibleAddressException;
import inet.ipaddr.PrefixLenException;
import inet.ipaddr.format.AddressDivisionBase;
import inet.ipaddr.format.util.AddressComponentSpliterator;
import inet.ipaddr.ipv4.IPv4AddressNetwork.IPv4AddressCreator;
import inet.ipaddr.ipv6.IPv6AddressNetwork.IPv6AddressCreator;
import inet.ipaddr.ipv6.IPv6AddressSegment;
/**
* This represents a segment of an IPv4 address. For IPv4, segments are 1 byte. For IPv6, they are two bytes.
*
* Like String and Integer and various others basic objects, segments are immutable, which also makes them thread-safe.
*
* @author sfoley
*
*/
public class IPv4AddressSegment extends IPAddressSegment implements Iterable {
private static final long serialVersionUID = 4L;
/**
* When printed with the default radix of 10, the max number of characters per segment
*/
public static final int MAX_CHARS = 3;
/**
* Constructs a segment of an IPv4 address with the given value.
*
* @throws AddressValueException if value is negative or too large
* @param value the value of the segment
*/
public IPv4AddressSegment(int value) throws AddressValueException {
super(value);
if(value > IPv4Address.MAX_VALUE_PER_SEGMENT) {
throw new AddressValueException(value);
}
}
/**
* Constructs a segment of an IPv4 address.
*
* @throws AddressValueException if value or prefix length is negative or too large
* @param value the value of the segment. If the segmentPrefixLength is non-null, the network prefix of the value is used, and the segment represents all segment values with the same network prefix.
* @param segmentPrefixLength the segment prefix, which can be null
*/
public IPv4AddressSegment(int value, Integer segmentPrefixLength) throws AddressValueException {
super(value, segmentPrefixLength);
if(value > IPv4Address.MAX_VALUE_PER_SEGMENT) {
throw new AddressValueException(value);
}
if(segmentPrefixLength != null && segmentPrefixLength > IPv4Address.BIT_COUNT) {
throw new PrefixLenException(segmentPrefixLength);
}
}
/**
* Constructs a segment of an IPv4 address that represents a range of values.
*
* @throws AddressValueException if either lower or upper value or prefix length is negative or too large
* @param segmentPrefixLength the segment prefix length, which can be null. If segmentPrefixLength is non-null, this segment represents a range of segment values with the given network prefix length.
* @param lower the lower value of the range of values represented by the segment. If segmentPrefixLength is non-null, the lower value becomes the smallest value with the same network prefix.
* @param upper the upper value of the range of values represented by the segment. If segmentPrefixLength is non-null, the upper value becomes the largest value with the same network prefix.
*/
public IPv4AddressSegment(int lower, int upper, Integer segmentPrefixLength) throws AddressValueException {
super(lower, upper, segmentPrefixLength);
if(getUpperSegmentValue() > IPv4Address.MAX_VALUE_PER_SEGMENT) {
throw new AddressValueException(getUpperSegmentValue());
}
if(segmentPrefixLength != null && segmentPrefixLength > IPv4Address.BIT_COUNT) {
throw new PrefixLenException(segmentPrefixLength);
}
}
@Override
public long getMaxValue() {
return IPv4Address.MAX_VALUE_PER_SEGMENT;
}
@Override
public boolean isIPv4() {
return true;
}
@Override
public IPVersion getIPVersion() {
return IPVersion.IPV4;
}
@Override
protected byte[] getBytesImpl(boolean low) {
return new byte[] {(byte) (low ? getSegmentValue() : getUpperSegmentValue())};
}
@Override
protected int getSegmentNetworkMask(int bits) {
return getNetwork().getSegmentNetworkMask(bits);
}
@Override
protected int getSegmentHostMask(int bits) {
return getNetwork().getSegmentHostMask(bits);
}
@Override
public int getMaxSegmentValue() {
return getMaxSegmentValue(IPVersion.IPV4);
}
protected IPv4AddressSegment toPrefixNormalizedSeg() {
return getSegmentCreator().createSegment(getSegmentValue(), getUpperSegmentValue(), IPv4AddressSection.cacheBits(getBitCount()));
}
protected IPv4AddressSegment toPrefixedSegment(Integer segmentPrefixLength) {
if(isChangedByPrefix(segmentPrefixLength, getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets())) {
return super.toPrefixedSegment(segmentPrefixLength, getSegmentCreator());
}
return this;
}
@Override
public IPv4AddressSegment toNetworkSegment(Integer segmentPrefixLength) {
return toNetworkSegment(segmentPrefixLength, true);
}
@Override
public IPv4AddressSegment toNetworkSegment(Integer segmentPrefixLength, boolean withPrefixLength) {
if(isNetworkChangedByPrefix(segmentPrefixLength, withPrefixLength)) {
return super.toNetworkSegment(segmentPrefixLength, withPrefixLength, getSegmentCreator());
}
return this;
}
@Override
public IPv4AddressSegment toHostSegment(Integer bits) {
if(isHostChangedByPrefix(bits)) {
return super.toHostSegment(bits, getSegmentCreator());
}
return this;
}
@Override
public IPv4AddressSegment getLower() {
return getLowestOrHighest(this, getSegmentCreator(), true);
}
@Override
public IPv4AddressSegment getUpper() {
return getLowestOrHighest(this, getSegmentCreator(), false);
}
@Override
public IPv4AddressNetwork getNetwork() {
return Address.defaultIpv4Network();
}
public IPv4AddressCreator getSegmentCreator() {
return getNetwork().getAddressCreator();
}
@Override
public Iterable getIterable() {
return this;
}
Iterator iterator(boolean withPrefix) {
IPv4AddressSegment original;
if(!withPrefix && isPrefixed() && !isMultiple()) {
original = withoutPrefixLength();
} else {
original = this;
}
return iterator(original, getSegmentCreator(), withPrefix ? getSegmentPrefixLength() : null, false, false);
}
@Override
public Iterator iterator() {
return iterator(!getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets());
}
@Override
public AddressComponentSpliterator spliterator() {
IPv4AddressCreator creator = getSegmentCreator();
boolean isAllSubnets = getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets();
Integer segPrefLength = isAllSubnets ? null : getSegmentPrefixLength();
int bitCount = getBitCount();
return createSegmentSpliterator(
this,
getSegmentValue(),
getUpperSegmentValue(),
this::iterator,
(isLowest, isHighest, value, upperValue) -> iterator(null, value, upperValue, bitCount, creator, segPrefLength, false, false),
(value, upperValue) -> creator.createSegment(value, upperValue, segPrefLength));
}
@Override
public Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
@Override
public Iterator prefixBlockIterator() {
return iterator(this, getSegmentCreator(), getSegmentPrefixLength(), true, true);
}
@Override
public AddressComponentSpliterator prefixBlockSpliterator() {
Integer segPrefLength = getSegmentPrefixLength();
if(segPrefLength == null) {
return spliterator();
}
return prefixBlockSpliterator(segPrefLength);
}
@Override
public Stream prefixBlockStream() {
return StreamSupport.stream(prefixBlockSpliterator(), false);
}
@Override
public Iterator prefixIterator() {
return iterator(this, getSegmentCreator(), getSegmentPrefixLength(), true, false);
}
@Override
public AddressComponentSpliterator prefixSpliterator() {
Integer segPrefLength = getSegmentPrefixLength();
if(segPrefLength == null) {
return spliterator();
}
return prefixSpliterator(
this,
segPrefLength,
getSegmentCreator(),
this::prefixIterator);
}
@Override
public Stream prefixStream() {
return StreamSupport.stream(prefixSpliterator(), false);
}
@Override
public Iterator prefixBlockIterator(int prefixLength) {
if(prefixLength < 0) {
throw new PrefixLenException(prefixLength);
}
return iterator(this, getSegmentCreator(), IPv4AddressSection.cacheBits(prefixLength), true, true);
}
@Override
public AddressComponentSpliterator prefixBlockSpliterator(int segPrefLength) {
return prefixBlockSpliterator(
this,
segPrefLength,
getSegmentCreator(),
this::prefixBlockIterator);
}
@Override
public Stream prefixBlockStream(int segPrefLength) {
return StreamSupport.stream(prefixBlockSpliterator(segPrefLength), false);
}
Iterator identityIterator() {
return identityIterator(this);
}
@Override
public int getBitCount() {
return IPv4Address.BITS_PER_SEGMENT;
}
@Override
public int getByteCount() {
return IPv4Address.BYTES_PER_SEGMENT;
}
@Override
public int getDefaultTextualRadix() {
return IPv4Address.DEFAULT_TEXTUAL_RADIX;
}
@Override
public int getMaxDigitCount() {
return MAX_CHARS;
}
@Override
public IPv4AddressSegment reverseBits(boolean perByte) {
return reverseBits();
}
public IPv4AddressSegment reverseBits() {
if(isMultiple()) {
if(isReversibleRange(this)) {
if(isPrefixed()) {
AddressSegmentCreator creator = getSegmentCreator();
return creator.createSegment(getSegmentValue(), getUpperSegmentValue(), null);
}
return this;
}
throw new IncompatibleAddressException(this, "ipaddress.error.reverseRange");
}
int oldVal = getSegmentValue();
int newVal = reverseBits((byte) oldVal);
if(oldVal == newVal && !isPrefixed()) {
return this;
}
AddressSegmentCreator creator = getSegmentCreator();
return creator.createSegment(newVal);
}
@Override
public IPv4AddressSegment reverseBytes() {
// Since a segment is already one byte, already reversed, but we do need to remove the prefix
return removePrefix(this, false, getSegmentCreator());
}
@Override
public IPv4AddressSegment toZeroHost() {
return toZeroHost(this, getSegmentCreator());
}
@Override @Deprecated
public IPv4AddressSegment removePrefixLength(boolean zeroed) {
return removePrefix(this, zeroed, getSegmentCreator());
}
@Override @Deprecated
public IPv4AddressSegment removePrefixLength() {
return removePrefixLength(true);
}
@Override
public IPv4AddressSegment withoutPrefixLength() {
return removePrefix(this, false, getSegmentCreator());
}
@Override
public boolean prefixContains(IPAddressSegment other, int segmentPrefixLength) {
return this == other || (super.prefixContains(other, segmentPrefixLength) && other instanceof IPv4AddressSegment);
}
@Override
public boolean prefixEquals(AddressSegment other, int segmentPrefixLength) {
return this == other || (super.prefixEquals(other, segmentPrefixLength) && other instanceof IPv4AddressSegment);
}
@Override
public boolean contains(AddressSegment other) {
return this == other || (containsSeg(other) && other instanceof IPv4AddressSegment);
}
@Override
public boolean equals(Object other) {
return this == other || (other instanceof IPv4AddressSegment && ((IPv4AddressSegment) other).isSameValues((AddressSegment) this));
}
@Override
protected boolean isSameValues(AddressDivisionBase other) {
return other instanceof IPv4AddressSegment && isSameValues((AddressSegment) other);
}
/**
* Joins with another IPv4 segment to produce a IPv6 segment.
*
* @param creator
* @param low
* @return
*/
public IPv6AddressSegment join(IPv6AddressCreator creator, IPv4AddressSegment low) throws IncompatibleAddressException {
int shift = IPv4Address.BITS_PER_SEGMENT;
Integer prefix = getJoinedSegmentPrefixLength(shift, getSegmentPrefixLength(), low.getSegmentPrefixLength());
if(isMultiple()) {
// if the high segment has a range, the low segment must match the full range,
// otherwise it is not possible to create an equivalent range when joining
if(!low.isFullRange()) {
throw new IncompatibleAddressException(this, low, "ipaddress.error.invalidMixedRange");
}
}
return creator.createSegment(
(getSegmentValue() << shift) | low.getSegmentValue(),
(getUpperSegmentValue() << shift) | low.getUpperSegmentValue(),
prefix);
}
static Integer getJoinedSegmentPrefixLength(int bitsPerSegment, Integer highBits, Integer lowBits) {
if(lowBits == null) {
return null;
}
if(lowBits == 0) {
return highBits;
}
return IPv4AddressSection.cacheBits(lowBits + bitsPerSegment);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy