org.zodiac.netty.http.headers.BoundedRange Maven / Gradle / Ivy
package org.zodiac.netty.http.headers;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.zodiac.sdk.toolkit.util.lang.StrUtil;
/**
* A range of bytes within some number of servable bytes.
*
* @see Range#toBoundedRange(long)
*
*/
public class BoundedRange {
private final Pattern RANGE_PATTERN = Pattern.compile("bytes (\\d+)-(\\d+)\\/([\\d\\*]+)");
private final Pattern INVALID_RANGE_PATTERN = Pattern.compile("bytes \\*\\/(\\d+)");
private long start;
private long end;
private long of;
private boolean valid;
public BoundedRange(long start, long end) {
this(start, end, -1);
}
public BoundedRange(long start, long end, long of) {
if (end < start) {
throw new IllegalArgumentException("End less than start: " + start + " end: " + end);
}
if ((of < start || of < end) && of != -1) {
throw new IllegalArgumentException("Total bytes less than end");
} else {
valid = true;
}
this.start = start;
this.end = end;
this.of = of;
}
public long length() {
return (end + 1) - start;
}
public BoundedRange(CharSequence value) {
value = StrUtil.trim(value);
Matcher m = RANGE_PATTERN.matcher(value);
if (m.find()) {
try {
start = Long.parseLong(m.group(1));
end = Long.parseLong(m.group(2));
if ("*".equals(m.group(3))) {
of = -1;
} else {
of = Long.parseLong(m.group(3));
}
valid = start < end && of >= end;
} catch (NumberFormatException nfe) {
valid = false;
}
} else {
m = INVALID_RANGE_PATTERN.matcher(value);
if (m.find()) {
start = -1;
end = -1;
try {
of = Long.parseLong(m.group(1));
valid = true;
} catch (NumberFormatException nfe) {
valid = false;
}
} else {
valid = false;
start = -1;
end = -1;
of = -1;
}
}
}
public boolean isRangeNotSatisfiable() {
return start == -1L && end == -1L && of > 0;
}
public boolean isValid() {
return valid;
}
public long start() {
return start;
}
public long end() {
return end;
}
public long of() {
return of;
}
public CharSequence toCharSequence() {
long start = start();
long end = end();
long of = of();
if (start == -1L && end == -1L) {
return "bytes */" + of;
}
return "bytes " + start + "-" + end + "/" + (of == -1L ? "*" : of);
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof BoundedRange) {
BoundedRange br = (BoundedRange) o;
return br.start == start && br.end == end && br.of == of;
}
return false;
}
@Override
public int hashCode() {
return Arrays.hashCode(new long[]{start, end, of});
}
@Override
public String toString() {
if (start == -1L && end == -1L) {
return "bytes */" + of;
}
return "bytes " + start + "-" + end + "/" + (of == -1L ? "*" : of);
}
public static BoundedRange unsatisfiable(long availableBytes) {
return new BoundedRange(-1, -1, availableBytes);
}
}