package ns.foundation;
import java.io.Serializable;
public class NSRange extends Object implements Serializable, Cloneable {
public static final NSRange ZeroRange = new NSRange();
/**
*
* @param string The string must be of the form "{location,length}"
* @return
*/
public static NSRange fromString(String string) {
if (string == null || !string.trim().matches("\\{[0-9]+,\\s*[0-9]+\\}"))
throw new IllegalArgumentException("Invalid argument to NSRange.fromString");
String str = string.trim();
str = str.substring(1, str.length()-1);
String[] parts = str.split(",\\s*");
return new NSRange(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
}
protected int location;
protected int length;
public NSRange() {
location = 0;
length = 0;
}
public NSRange(int location, int length) {
this(location, length, true);
}
private NSRange(int location, int length, boolean checkValues)
{
this.location = 0;
this.length = 0;
if (checkValues) {
if (location < 0)
throw new IllegalArgumentException("Cannot create an" + super.getClass().getName() + " with negative location.");
if (length < 0)
throw new IllegalArgumentException("Cannot create an" + super.getClass().getName() + " with negative length.");
if (location - 1 > 2147483647 - length)
throw new IllegalArgumentException("Range endpoint greater than Integer.MAX_VALUE");
}
this.location = location;
this.length = length;
}
public NSRange(NSRange range) {
this();
if (range != null) {
this.location = range.location();
this.length = range.length();
}
}
public int location() {
return location;
}
public int length() {
return length;
}
public boolean isEqualToRange(NSRange otherRange) {
return equals(otherRange);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + length;
result = prime * result + location;
return result;
}
@Override
public boolean equals(Object obj) {
if (super.equals(obj))
return true;
if (!(obj instanceof NSRange))
return false;
final NSRange other = (NSRange) obj;
return location == other.location && length == other.length;
}
@Override
public String toString() {
return "{" + location + ", " + length + "}";
}
@Override
public Object clone() {
return this;
}
public boolean containsLocation(int _location) {
return _location >= location && _location < this.maxRange();
}
public boolean intersectsRange(NSRange otherRange) {
if (otherRange == null)
return false;
if (otherRange.location >= location &&
otherRange.location <= maxRange())
return true; // starts in this range
else if (otherRange.maxRange() >= location &&
otherRange.maxRange() <= maxRange())
return true; // ends in this range
else
return false;
}
public boolean isEmpty() {
return length == 0;
}
public boolean isSubrangeOfRange(NSRange otherRange) {
if (otherRange == null)
return false;
return (otherRange.location <= location &&
otherRange.maxRange() >= maxRange());
}
public int maxRange() {
return location + length;
}
public NSRange rangeByIntersectingRange(NSRange otherRange) {
if (otherRange == null)
return ZeroRange;
int start = Math.max(location, otherRange.location());
int end = Math.min(maxRange(), otherRange.maxRange());
return new NSRange(start, end - start);
}
public NSRange rangeByUnioningRange(NSRange otherRange) {
if (otherRange == null)
return this;
int start = Math.min(location, otherRange.location());
int end = Math.max(maxRange(), otherRange.maxRange());
return new NSRange(start, end - start);
}
public void subtractRange(NSRange otherRange, NSMutableRange resultRange1, NSMutableRange resultRange2) {
NSRange intersection = rangeByIntersectingRange(otherRange);
// no intersection, return empty range
if (intersection.isEmpty()) {
resultRange1.setLocation(0);
resultRange1.setLength(0);
resultRange2.setLocation(0);
resultRange2.setLength(0);
// total intersection, return empty range
} else if (intersection.location() == location() && intersection.length() == length()) {
resultRange1.setLocation(0);
resultRange1.setLength(0);
resultRange2.setLocation(0);
resultRange2.setLength(0);
// intersects from the start, single result with the remaining range
} else if (intersection.location() == location()) {
resultRange1.setLocation(intersection.maxRange());
resultRange1.setLength(length() - intersection.length());
resultRange2.setLocation(0);
resultRange2.setLength(0);
// intersects from the end, single result with the beginning range
} else {
resultRange1.setLocation(intersection.location-1);
resultRange1.setLength(length() - intersection.length());
resultRange2.setLocation(0);
resultRange2.setLength(0);
}
}
}