/* * 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.format; import java.math.BigInteger; import inet.ipaddr.AddressNetwork; import inet.ipaddr.PrefixLenException; import inet.ipaddr.format.string.AddressStringDivisionSeries; /** * Represents a series of groups of address divisions or segments. Each group may have a different bit size. * * This interface is the super interface of all interfaces and classes representing a series of divisions or segments. * * @author sfoley * */ public interface AddressDivisionSeries extends AddressItem, AddressStringDivisionSeries { /** * Use this method to compare the counts of two address series. * * Rather than calculating counts with getCount(), there can be more efficient ways of comparing whether one series represents more individual address series than another. * * @return a positive integer if this AddressDivisionSeries has a larger count than the provided, 0 if they are the same, a negative integer if the other has a larger count. */ default int isMore(AddressDivisionSeries other) { if(!isMultiple()) { return other.isMultiple() ? -1 : 0; } if(!other.isMultiple()) { return 1; } return getCount().compareTo(other.getCount()); } /** * @return the given division in this series. The first is at index 0. */ @Override AddressGenericDivision getDivision(int index); /** * Get standard-format strings for each of the divisions in the series. * * @return */ String[] getDivisionStrings(); /** * The bit-length of the portion of the address that is not specific to an individual address but common amongst a group of addresses. * <p> * Typically this is the largest number of bits in the upper-most portion of the section for which the remaining bits assume all possible values. * <p> * For IP addresses, this must be explicitly defined when the address is created. For example, 1.2.0.0/16 has a prefix length of 16, while 1.2.*.* has no prefix length, * even though they both represent the same set of addresses and are considered equal. Prefixes can be considered variable for any given IP addresses and can * depend on the routing table. * <p> * The methods {@link AddressDivisionSeries#getMinPrefixLengthForBlock()} and {@link AddressDivisionSeries#getPrefixLengthForSingleBlock()} can help you to obtain or define a prefix length if one does not exist already. * 1.2.0.0/16 and 1.2.*.* both the same equivalent and minimum prefix length of 16. * <p> * For MAC addresses, the prefix is initially defined by the range, so 1:2:3:*:*:* has a prefix length of 24 by definition. Addresses derived from the original may retain the original prefix length regardless of their range. * <p> */ Integer getPrefixLength(); /** * Whether there exists a prefix length associated with this series. */ boolean isPrefixed(); /** * Returns whether this address segment series represents a block of addresses associated with its prefix length. * <p> * This returns false if it has no prefix length or if it is a range of addresses that does not include * the entire subnet block for the prefix length. * <p> * If {@link AddressNetwork#getPrefixConfiguration} is set to consider all prefixes as subnets, this returns true for any series with a prefix length. * <p> * An important distinction of {@link #containsPrefixBlock(int)} with this method is that this method returns * false if the series does not have a prefix length assigned to it, * even if there exists one or more prefix lengths for which {@link #containsPrefixBlock(int)} returns true. * @return */ boolean isPrefixBlock(); /** * Returns whether the range of values matches a single subnet block for the prefix length * <p> * An important distinction of this method with {@link #containsSinglePrefixBlock(int)} is that this method returns * false if the series does not have a prefix length assigned to it, * even if there exists a prefix length for which {@link #containsSinglePrefixBlock(int)} * returns true. * * * @return */ boolean isSinglePrefixBlock(); /** * If this has a prefix length, the count of the range of values in the prefix. * <p> * If this has no prefix length, returns the same value as {@link #getCount()} * * @return */ default BigInteger getPrefixCount() { Integer prefixLength = getPrefixLength(); if(prefixLength == null || prefixLength >= getBitCount()) { return getCount(); } return getPrefixCount(prefixLength); } @Override default BigInteger getPrefixCount(int prefixLength) { if(prefixLength < 0 || prefixLength > getBitCount()) { throw new PrefixLenException(this, prefixLength); } BigInteger result = BigInteger.ONE; if(isMultiple()) { int divisionCount = getDivisionCount(); int divPrefixLength = prefixLength; for(int i = 0; i < divisionCount; i++) { AddressGenericDivision division = getDivision(i); int divBitCount = division.getBitCount(); if(division.isMultiple()) { BigInteger divCount = (divPrefixLength < divBitCount) ? division.getPrefixCount(divPrefixLength) : division.getCount(); result = result.multiply(divCount); } if(divPrefixLength <= divBitCount) { break; } divPrefixLength -= divBitCount; } } return result; } @Override default BigInteger getCount() { BigInteger result = BigInteger.ONE; int count = getDivisionCount(); if(count > 0) { for(int i = 0; i < count; i++) { AddressGenericDivision div = getDivision(i); if(div.isMultiple()) { BigInteger divCount = getDivision(i).getCount(); result = result.multiply(divCount); } } } return result; } /** * Returns the count of values in the initial (higher) count of divisions. * * @return */ default BigInteger getBlockCount(int divCount) { if(divCount < 0) { throw new IllegalArgumentException(); } BigInteger result = BigInteger.ONE; int divisionCount = getDivisionCount(); if(divCount < divisionCount) { divisionCount = divCount; } for(int i = 0; i < divisionCount; i++) { AddressGenericDivision division = getDivision(i); if(division.isMultiple()) { result = result.multiply(division.getCount()); } } return result; } @Override default int getBitCount() { int count = getDivisionCount(); int bitCount = 0; for(int i = 0; i < count; i++) { bitCount += getDivision(i).getBitCount(); } return bitCount; } /** * Returns whether the series represents a range of values that are sequential. * <p> * Generally, this means that any division covering a range of values must be followed by divisions that are full range, covering all values. * * @return */ default boolean isSequential() { int count = getDivisionCount(); if(count > 1) { for(int i = 0; i < count; i++) { if(getDivision(i).isMultiple()) { for(++i; i < count; i++) { if(!getDivision(i).isFullRange()) { return false; } } } } } return true; } }