inet.ipaddr.mac.MACAddressSegment 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.mac;
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.IncompatibleAddressException;
import inet.ipaddr.PrefixLenException;
import inet.ipaddr.format.AddressDivisionBase;
import inet.ipaddr.format.standard.AddressDivision;
import inet.ipaddr.format.standard.AddressDivisionGrouping.StringOptions;
import inet.ipaddr.format.util.AddressComponentSpliterator;
import inet.ipaddr.format.util.AddressDivisionWriter;
import inet.ipaddr.mac.MACAddressNetwork.MACAddressCreator;
import inet.ipaddr.mac.MACAddressSection.MACStringCache;
/**
* Represents a segment of a MAC address. For MAC, segments are 1 byte.
*
* Segments are immutable, which also makes them thread-safe.
*
* @author sfoley
*
*/
public class MACAddressSegment extends AddressDivision implements AddressSegment, Iterable {
private static final long serialVersionUID = 4L;
public static final int MAX_CHARS = 2;
private final int value; //the lower value of the segment
private final int upperValue; //the upper value of a range; if not a range it is the same as value
/**
* Constructs a segment of an IPv4 or IPv6 address with the given value.
*
* @throws AddressValueException if value is negative or too large
* @param value the value of the segment
*/
public MACAddressSegment(int value) {
if(value < 0 || value > MACAddress.MAX_VALUE_PER_SEGMENT) {
throw new AddressValueException(value);
}
this.value = this.upperValue = value;
}
/**
* Constructs a segment of a MAC address that represents a range of values.
*
* @throws AddressValueException if value is negative or too large
* @param lower the lower value of the range of values represented by the segment.
* @param upper the upper value of the range of values represented by the segment.
*/
public MACAddressSegment(int lower, int upper) {
if(lower > upper) {
int tmp = lower;
lower = upper;
upper = tmp;
}
if(lower < 0 || upper < 0 || upper > MACAddress.MAX_VALUE_PER_SEGMENT) {
throw new AddressValueException(lower < 0 ? lower : upper);
}
this.value = lower;
this.upperValue = upper;
}
@Override
protected byte[] getBytesImpl(boolean low) {
return new byte[] { (byte) (low ? getSegmentValue() : getUpperSegmentValue())};
}
protected boolean isPrefixBlock(int segmentPrefixLength) {
if(segmentPrefixLength < MACAddress.BITS_PER_SEGMENT) {
int mask = ~0 << (MACAddress.BITS_PER_SEGMENT - segmentPrefixLength);
int lower = getSegmentValue();
int newLower = lower & mask;
if(lower != newLower) {
return false;
}
int upper = getUpperSegmentValue();
return upper == (upper | ~mask);
}
return true;
}
protected MACAddressSegment toPrefixBlockSegment(int segmentPrefixLength) {
if(segmentPrefixLength < MACAddress.BITS_PER_SEGMENT && !isPrefixBlock(segmentPrefixLength)) {
int lower = getSegmentValue();
int upper = getUpperSegmentValue();
int mask = ~0 << (MACAddress.BITS_PER_SEGMENT - segmentPrefixLength);
lower &= mask;
upper |= ~mask;
return getSegmentCreator().createRangeSegment(lower, upper);
}
return this;
}
protected MACAddressSegment setPrefixedSegment(Integer oldPrefixLength, Integer segmentPrefixLength, boolean zeroed) {
return setPrefixedSegment(this, oldPrefixLength, segmentPrefixLength, zeroed, getSegmentCreator());
}
private MACAddressCreator getSegmentCreator() {
return getNetwork().getAddressCreator();
}
@Override
public MACAddressNetwork getNetwork() {
return MACAddress.defaultMACNetwork();
}
@Override
public int getValueCount() {
return getUpperSegmentValue() - getSegmentValue() + 1;
}
@Override
public int getPrefixValueCount(int segmentPrefixLength) {
return getPrefixValueCount(this, segmentPrefixLength);
}
@Override
public int getBitCount() {
return MACAddress.BITS_PER_SEGMENT;
}
@Override
public int getByteCount() {
return MACAddress.BYTES_PER_SEGMENT;
}
@Override
public long getMaxValue() {
return MACAddress.MAX_VALUE_PER_SEGMENT;
}
@Override
public long getDivisionValue() {
return getSegmentValue();
}
@Override
public long getUpperDivisionValue() {
return getUpperSegmentValue();
}
/**
* returns the lower value
*/
@Override
public int getSegmentValue() {
return value;
}
/**
* returns the upper value
*/
@Override
public int getUpperSegmentValue() {
return upperValue;
}
private MACAddressSegment getLowestOrHighest(boolean lowest) {
if(!isMultiple()) {
return this;
}
return getSegmentCreator().createSegment(lowest ? getSegmentValue() : getUpperSegmentValue());
}
@Override
public MACAddressSegment getLower() {
return getLowestOrHighest(true);
}
@Override
public MACAddressSegment getUpper() {
return getLowestOrHighest(false);
}
@Override
public MACAddressSegment reverseBits(boolean perByte) {
return reverseBits();
}
public MACAddressSegment reverseBits() {
if(isMultiple()) {
if(isReversibleRange(this)) {
return this;
}
throw new IncompatibleAddressException(this, "ipaddress.error.reverseRange");
}
int oldValue = value;
int newValue = reverseBits((byte) oldValue);
if(oldValue == newValue) {
return this;
}
AddressSegmentCreator creator = getSegmentCreator();
return creator.createSegment(newValue);
}
@Override
public MACAddressSegment reverseBytes() {
return this;
}
@Override
public boolean isBoundedBy(int value) {
return getUpperSegmentValue() < value;
}
@Override
protected boolean isSameValues(AddressDivisionBase other) {
return other instanceof MACAddressSegment && isSameValues((MACAddressSegment) other);
}
protected boolean isSameValues(MACAddressSegment otherSegment) {
return value == otherSegment.value && upperValue == otherSegment.upperValue;
}
@Override
public int hashCode() {
return hash(value, upperValue, getBitCount());
}
static int hash(int lower, int upper, int bitCount) {
return lower | (upper << bitCount);
}
@Override
public boolean equals(Object other) {
return this == other || (other instanceof MACAddressSegment && ((MACAddressSegment) other).isSameValues(this));
}
/**
*
* @param other
* @return whether this subnet segment contains the given address segment
*/
public boolean contains(MACAddressSegment other) {
return other.value >= value && other.upperValue <= upperValue;
}
@Override
public int getDefaultTextualRadix() {
return MACAddress.DEFAULT_TEXTUAL_RADIX;
}
@Override
public int getMaxDigitCount() {
return MAX_CHARS;
}
@Override
public boolean matches(int value) {
return super.matches(value);
}
@Override
public boolean matchesWithMask(int value, int mask) {
return super.matchesWithMask(value, mask);
}
@Override
public boolean matchesWithMask(int lowerValue, int upperValue, int mask) {
return super.matchesWithMask(lowerValue, upperValue, mask);
}
void setString(
CharSequence addressStr,
boolean isStandardString,
int lowerStringStartIndex,
int lowerStringEndIndex,
int originalLowerValue) {
if(cachedWildcardString == null && isStandardString && originalLowerValue == getDivisionValue()) {
cachedWildcardString = addressStr.subSequence(lowerStringStartIndex, lowerStringEndIndex).toString();
}
}
void setString(CharSequence addressStr,
boolean isStandardRangeString,
int lowerStringStartIndex,
int upperStringEndIndex,
int rangeLower,
int rangeUpper) {
if(cachedWildcardString == null) {
if(isFullRange()) {
cachedWildcardString = MACAddress.SEGMENT_WILDCARD_STR;
} else if(isStandardRangeString && rangeLower == getDivisionValue() && rangeUpper == getUpperDivisionValue()) {
cachedWildcardString = addressStr.subSequence(lowerStringStartIndex, upperStringEndIndex).toString();
}
}
}
@Override
public Iterable getIterable() {
return this;
}
@Override
public Iterator iterator() {
return iterator(this, getSegmentCreator(), null, false, false);
}
@Override
public AddressComponentSpliterator spliterator() {
MACAddressCreator creator = getSegmentCreator();
int bitCount = getBitCount();
return createSegmentSpliterator(
this,
getSegmentValue(),
getUpperSegmentValue(),
this::iterator,
(isLowest, isHighest, value, upperValue) -> iterator(null, value, upperValue, bitCount, creator, null, false, false),
(value, upperValue) -> creator.createSegment(value, upperValue, null));
}
@Override
public Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
Iterator prefixBlockIterator(int segmentPrefixLength) {
return iterator(this, getSegmentCreator(), segmentPrefixLength, true, true);
}
Iterator prefixIterator(int segmentPrefixLength) {
return iterator(this, getSegmentCreator(), segmentPrefixLength, true, false);
}
@Override
public int getMaxSegmentValue() {
return MACAddress.MAX_VALUE_PER_SEGMENT;
}
@Override
public boolean prefixEquals(AddressSegment o, int segmentPrefixLength) {
if(segmentPrefixLength < 0) {
throw new PrefixLenException(segmentPrefixLength);
}
if(o instanceof MACAddressSegment) {
MACAddressSegment other = (MACAddressSegment) o;
int shift = getBitCount() - segmentPrefixLength;
if(shift <= 0) {
return isSameValues(other);
}
return (other.getSegmentValue() >>> shift) == (getSegmentValue() >>> shift) &&
(other.getUpperSegmentValue() >>> shift) <= (getUpperSegmentValue() >>> shift);
}
return false;
}
@Override
public boolean contains(AddressSegment other) {
return other instanceof MACAddressSegment && other.getSegmentValue() >= value && other.getUpperSegmentValue() <= upperValue;
}
@Override
protected String getDefaultSegmentWildcardString() {
return Address.SEGMENT_WILDCARD_STR;
}
@Override
public String toHexString(boolean with0xPrefix) {
return toNormalizedString(with0xPrefix ? MACStringCache.hexPrefixedParams : MACStringCache.hexParams);
}
@Override
public String toNormalizedString() {
return toNormalizedString(MACStringCache.canonicalParams);
}
public String toNormalizedString(StringOptions options) {
AddressDivisionWriter params = MACAddressSection.toParams(options);
StringBuilder builder = new StringBuilder(params.getDivisionStringLength(this));
return params.appendDivision(builder, this).toString();
}
/**
* @return whether the division range includes the block of values for the given prefix length
*/
@Override
public boolean containsPrefixBlock(int divisionPrefixLen) {
return isPrefixBlock(getDivisionValue(), getUpperDivisionValue(), divisionPrefixLen);
}
/**
* Returns whether the division range matches exactly the block of values for the given prefix length.
*
* @return whether the range of this division matches the range for a single prefix with a single value and the given prefix length.
*
* @param divisionPrefixLen
* @return whether the range of this segment matches the block of address divisions for that prefix.
*/
@Override
public boolean containsSinglePrefixBlock(int divisionPrefixLen) {
return isSinglePrefixBlock(getDivisionValue(), getUpperDivisionValue(), divisionPrefixLen);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy