package org.batfish.datamodel;
import java.io.Serializable;
import org.batfish.common.BatfishException;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
public final class Prefix implements Comparable<Prefix>, Serializable {
public static final int MAX_PREFIX_LENGTH = 32;
/**
*
*/
private static final long serialVersionUID = 1L;
public static final Prefix ZERO = new Prefix(new Ip(0l), 0);
private static long getNetworkEnd(long networkStart, int prefix_length) {
long networkEnd = networkStart;
int ones_length = 32 - prefix_length;
for (int i = 0; i < ones_length; i++) {
networkEnd |= ((long) 1 << i);
}
return networkEnd;
}
private static long numWildcardBitsToWildcardLong(int numBits) {
long wildcard = 0;
for (int i = 0; i < numBits; i++) {
wildcard |= (1l << i);
}
return wildcard;
}
private Ip _address;
private int _prefixLength;
public Prefix(Ip address, int prefixLength) {
if (address == null) {
throw new BatfishException("Cannot create prefix with null network");
}
_address = address;
_prefixLength = prefixLength;
}
public Prefix(Ip address, Ip mask) {
if (address == null) {
throw new BatfishException("Cannot create prefix with null network");
}
if (mask == null) {
throw new BatfishException("Cannot create prefix with null mask");
}
_address = address;
_prefixLength = mask.numSubnetBits();
}
@JsonCreator
public Prefix(String text) {
String[] parts = text.split("/");
if (parts.length != 2) {
throw new BatfishException("Invalid prefix string: \"" + text + "\"");
}
_address = new Ip(parts[0]);
try {
_prefixLength = Integer.parseInt(parts[1]);
}
catch (NumberFormatException e) {
throw new BatfishException(
"Invalid prefix length: \"" + parts[1] + "\"", e);
}
}
@Override
public int compareTo(Prefix rhs) {
int ret = _address.compareTo(rhs._address);
if (ret != 0) {
return ret;
}
return Integer.compare(_prefixLength, rhs._prefixLength);
}
public boolean contains(Ip ip) {
long start = getNetworkAddress().asLong();
long end = getEndAddress().asLong();
long ipAsLong = ip.asLong();
return (start <= ipAsLong && ipAsLong <= end);
}
public boolean containsPrefix(Prefix prefix) {
return contains(prefix._address) && _prefixLength < prefix._prefixLength;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
Prefix rhs = (Prefix) obj;
return _address.equals(rhs._address)
&& _prefixLength == rhs._prefixLength;
}
public Ip getAddress() {
return _address;
}
public Ip getEndAddress() {
return new Ip(getNetworkEnd(_address.asLong(), _prefixLength));
}
public Ip getNetworkAddress() {
return _address.getNetworkAddress(_prefixLength);
}
public Prefix getNetworkPrefix() {
return new Prefix(getNetworkAddress(), _prefixLength);
}
public int getPrefixLength() {
return _prefixLength;
}
public Ip getPrefixWildcard() {
int numWildcardBits = MAX_PREFIX_LENGTH - _prefixLength;
long wildcardLong = numWildcardBitsToWildcardLong(numWildcardBits);
return new Ip(wildcardLong);
}
public Ip getSubnetMask() {
return Ip.numSubnetBitsToSubnetMask(_prefixLength);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + _address.hashCode();
result = prime * result + _prefixLength;
return result;
}
@Override
@JsonValue
public String toString() {
return _address.toString() + "/" + _prefixLength;
}
}