Test buffers
This commit is contained in:
parent
95d8811bcb
commit
1eb4b0334c
@ -9,6 +9,7 @@ import java.nio.charset.Charset;
|
||||
import java.util.RandomAccess;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
public interface Buf extends ByteList, RandomAccess {
|
||||
static Buf wrap(ByteList bytes) {
|
||||
@ -30,7 +31,7 @@ public interface Buf extends ByteList, RandomAccess {
|
||||
}
|
||||
}
|
||||
|
||||
static Buf wrap(byte[] bytes) {
|
||||
static Buf wrap(byte... bytes) {
|
||||
return ByteListBuf.wrap(bytes);
|
||||
}
|
||||
|
||||
@ -87,6 +88,9 @@ public interface Buf extends ByteList, RandomAccess {
|
||||
@Override
|
||||
Buf subList(int from, int to);
|
||||
|
||||
@VisibleForTesting
|
||||
Buf subListForced(int from, int to);
|
||||
|
||||
Buf copyOfRange(int from, int to);
|
||||
|
||||
Buf copy();
|
||||
|
@ -25,6 +25,7 @@ public class BufDataInput extends SafeDataInputStream {
|
||||
@Deprecated
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,14 +43,21 @@ public class BufDataInput extends SafeDataInputStream {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public @NotNull String readUTF() {
|
||||
var length = this.readUnsignedShort();
|
||||
return this.in.readString(length, StandardCharsets.UTF_8);
|
||||
return readShortText(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString(int length, Charset charset) {
|
||||
return in.readString(length, charset);
|
||||
public @NotNull String readShortText(Charset charset) {
|
||||
var length = this.readUnsignedShort();
|
||||
return this.readString(length, charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String readMediumText(Charset charset) {
|
||||
var length = this.readInt();
|
||||
return this.readString(length, charset);
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,13 @@ import it.cavallium.stream.SafeDataOutput;
|
||||
import it.cavallium.stream.SafeDataOutputStream;
|
||||
import it.unimi.dsi.fastutil.Arrays;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static java.util.Objects.checkFromToIndex;
|
||||
|
||||
public class BufDataOutput implements SafeDataOutput {
|
||||
|
||||
private final SafeByteArrayOutputStream buf;
|
||||
@ -60,7 +63,7 @@ public class BufDataOutput implements SafeDataOutput {
|
||||
}
|
||||
|
||||
public static BufDataOutput wrap(Buf buf, int from, int to) {
|
||||
Arrays.ensureFromTo(buf.size(), from, to);
|
||||
checkFromToIndex(from, to, buf.size());
|
||||
if (buf.isEmpty()) {
|
||||
return createLimited(0);
|
||||
} else {
|
||||
@ -201,9 +204,15 @@ public class BufDataOutput implements SafeDataOutput {
|
||||
+ actualLength + " bytes";
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void writeUTF(@NotNull String str) {
|
||||
var out = str.getBytes(StandardCharsets.UTF_8);
|
||||
writeShortText(str, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShortText(String s, Charset charset) {
|
||||
var out = s.getBytes(charset);
|
||||
if (out.length > Short.MAX_VALUE) {
|
||||
throw new IndexOutOfBoundsException("String too long: " + out.length + " bytes");
|
||||
}
|
||||
@ -212,6 +221,14 @@ public class BufDataOutput implements SafeDataOutput {
|
||||
dOut.write(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeMediumText(String s, Charset charset) {
|
||||
var out = s.getBytes(charset);
|
||||
checkOutOfBounds(Integer.BYTES + out.length);
|
||||
dOut.writeInt(out.length);
|
||||
dOut.write(out);
|
||||
}
|
||||
|
||||
public Buf asList() {
|
||||
dOut.flush();
|
||||
return Buf.wrap(this.buf.array, this.buf.length);
|
||||
|
@ -1,33 +1,29 @@
|
||||
package it.cavallium.buffer;
|
||||
|
||||
import static it.unimi.dsi.fastutil.Arrays.ensureFromTo;
|
||||
import static java.util.Objects.checkFromToIndex;
|
||||
|
||||
import it.cavallium.stream.SafeByteArrayInputStream;
|
||||
import it.cavallium.stream.SafeByteArrayOutputStream;
|
||||
import it.cavallium.stream.SafeDataOutput;
|
||||
import it.unimi.dsi.fastutil.bytes.AbstractByteList;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteArrayList;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteArrays;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteCollection;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteConsumer;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteIterator;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteIterators;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteList;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteListIterator;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteSpliterator;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteSpliterators;
|
||||
import it.unimi.dsi.fastutil.bytes.*;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.*;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
class ByteListBuf extends ByteArrayList implements Buf {
|
||||
|
||||
private boolean mutable = true;
|
||||
private static final String IMMUTABLE_ERROR = "The buffer is immutable";
|
||||
private boolean immutable;
|
||||
|
||||
protected ByteListBuf(byte[] a, boolean wrapped) {
|
||||
super(a, wrapped);
|
||||
@ -151,19 +147,24 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return mutable;
|
||||
return !immutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteListBuf freeze() {
|
||||
mutable = false;
|
||||
immutable = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buf subList(int from, int to) {
|
||||
if (from == 0 && to == size()) return this;
|
||||
ensureFromTo(this.size(), from, to);
|
||||
return subListForced(from, to);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public Buf subListForced(int from, int to) {
|
||||
checkFromToIndex(from, to, this.size());
|
||||
return new SubList(from, to);
|
||||
}
|
||||
|
||||
@ -193,12 +194,15 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
|
||||
@Override
|
||||
public SafeByteArrayOutputStream binaryOutputStream(int from, int to) {
|
||||
ensureFromTo(size, from, to);
|
||||
checkFromToIndex(from, to, size);
|
||||
return new SafeByteArrayOutputStream(a, from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(int aStartIndex, Buf b, int bStartIndex, int length) {
|
||||
if (aStartIndex + length > size()) {
|
||||
return false;
|
||||
}
|
||||
return b.equals(bStartIndex, this.a, aStartIndex, length);
|
||||
}
|
||||
|
||||
@ -208,6 +212,9 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
if (aStartIndex + length > this.size) {
|
||||
return false;
|
||||
}
|
||||
if (bStartIndex + length > b.length) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.equals(a, aStartIndex, aStartIndex + length, b, bStartIndex, bStartIndex + length);
|
||||
}
|
||||
|
||||
@ -227,13 +234,21 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
// Most of the inherited methods should be fine, but we can override a few of them for performance.
|
||||
// Needed because we can't access the parent class' instance variables directly in a different
|
||||
// instance of SubList.
|
||||
@IgnoreCoverage
|
||||
private byte[] getParentArray() {
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Buf subList(int from, int to) {
|
||||
ensureFromTo(this.to, from, to);
|
||||
// Sadly we have to rewrap this, because if there is a sublist of a sublist, and the
|
||||
// subsublist adds, both sublists need to update their "to" value.
|
||||
return subListForced(from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buf subListForced(int from, int to) {
|
||||
checkFromToIndex(from, to, this.to);
|
||||
var fromAbs = this.from + from;
|
||||
var toAbs = this.from + to;
|
||||
// Sadly we have to rewrap this, because if there is a sublist of a sublist, and the
|
||||
@ -267,12 +282,15 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
|
||||
@Override
|
||||
public SafeByteArrayOutputStream binaryOutputStream(int from, int to) {
|
||||
ensureFromTo(size(), from, to);
|
||||
checkFromToIndex(from, to, size());
|
||||
return new SafeByteArrayOutputStream(a, from + this.from, to + this.from);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(int aStartIndex, Buf b, int bStartIndex, int length) {
|
||||
if (aStartIndex + length > size()) {
|
||||
return false;
|
||||
}
|
||||
return b.equals(bStartIndex, a, aStartIndex + from, length);
|
||||
}
|
||||
|
||||
@ -280,9 +298,11 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
public boolean equals(int aStartIndex, byte[] b, int bStartIndex, int length) {
|
||||
var aFrom = from + aStartIndex;
|
||||
var aTo = from + aStartIndex + length;
|
||||
var bTo = bStartIndex + length;
|
||||
if (aFrom < from) return false;
|
||||
if (aTo > to) return false;
|
||||
return Arrays.equals(a, aFrom, aTo, b, bStartIndex, bStartIndex + length);
|
||||
if (bTo > b.length) return false;
|
||||
return Arrays.equals(a, aFrom, aTo, b, bStartIndex, bTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -329,12 +349,12 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return mutable;
|
||||
return ByteListBuf.this.isMutable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubList freeze() {
|
||||
mutable = false;
|
||||
immutable = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -345,23 +365,30 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
super(0, index);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
protected byte get(int i) {
|
||||
return a[from + i];
|
||||
return ByteListBuf.SubList.this.getByte(i);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
protected void add(int i, byte k) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
ByteListBuf.SubList.this.add(i, k);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
protected void set(int i, byte k) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
ByteListBuf.SubList.this.set(i, k);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
protected void remove(int i) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
ByteListBuf.SubList.this.removeByte(i);
|
||||
}
|
||||
|
||||
@ -411,6 +438,7 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
return to;
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
protected byte get(int i) {
|
||||
return a[i];
|
||||
@ -482,4 +510,336 @@ class ByteListBuf extends ByteArrayList implements Buf {
|
||||
return new String(a, from, size(), charset);
|
||||
}
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void add(int index, byte k) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.add(index, k);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean add(byte k) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.add(k);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public byte removeByte(int index) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.removeByte(index);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean rem(byte k) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.rem(k);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public byte set(int index, byte k) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.set(index, k);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void clear() {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.clear();
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void trim() {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.trim();
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void trim(int n) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.trim(n);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void removeElements(int from, int to) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.removeElements(from, to);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void addElements(int index, byte[] a, int offset, int length) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.addElements(index, a, offset, length);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void setElements(int index, byte[] a, int offset, int length) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.setElements(index, a, offset, length);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean addAll(int index, ByteCollection c) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.addAll(index, c);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean addAll(int index, ByteList l) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.addAll(index, l);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean removeAll(ByteCollection c) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.removeAll(c);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean addAll(int index, @NotNull Collection<? extends Byte> c) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.addAll(index, c);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean addAll(@NotNull Collection<? extends Byte> c) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void addElements(int index, byte[] a) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.addElements(index, a);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void push(byte o) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.push(o);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public byte popByte() {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.popByte();
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public byte topByte() {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.topByte();
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean addAll(ByteCollection c) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean add(Byte key) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.add(key);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean remove(Object key) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.remove(key);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean removeAll(@NotNull Collection<?> c) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.removeAll(c);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean retainAll(ByteCollection c) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.retainAll(c);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean retainAll(@NotNull Collection<?> c) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.retainAll(c);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void setElements(byte[] a) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.setElements(a);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void setElements(int index, byte[] a) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.setElements(index, a);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public void add(int index, Byte key) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.add(index, key);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void replaceAll(ByteUnaryOperator operator) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.replaceAll(operator);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public void replaceAll(IntUnaryOperator operator) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.replaceAll(operator);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<Byte> operator) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.replaceAll(operator);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public Byte remove(int index) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.remove(index);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public Byte set(int index, Byte k) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.set(index, k);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean addAll(ByteList l) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.addAll(l);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public void sort(Comparator<? super Byte> comparator) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.sort(comparator);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public void unstableSort(Comparator<? super Byte> comparator) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.unstableSort(comparator);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean removeIf(Predicate<? super Byte> filter) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.removeIf(filter);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean removeIf(BytePredicate filter) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.removeIf(filter);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public boolean removeIf(IntPredicate filter) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.removeIf(filter);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public void push(Byte o) {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
super.push(o);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public Byte pop() {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.pop();
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@Override
|
||||
public Byte top() {
|
||||
assert isMutable() : IMMUTABLE_ERROR;
|
||||
return super.top();
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
private void ensureMutable() {
|
||||
if (!isMutable()) {
|
||||
throw new UnsupportedOperationException(IMMUTABLE_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
package it.cavallium.buffer;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface IgnoreCoverage {
|
||||
}
|
@ -3,6 +3,8 @@ package it.cavallium.data.generator.nativedata;
|
||||
import it.cavallium.data.generator.DataSerializer;
|
||||
import it.cavallium.stream.SafeDataInput;
|
||||
import it.cavallium.stream.SafeDataOutput;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -21,7 +23,7 @@ public class ArrayStringSerializer implements DataSerializer<List<String>> {
|
||||
public List<String> deserialize(SafeDataInput dataInput) {
|
||||
var data = new String[dataInput.readInt()];
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
data[i] = dataInput.readUTF();
|
||||
data[i] = dataInput.readShortText(StandardCharsets.UTF_8);
|
||||
}
|
||||
return List.of(data);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import it.cavallium.stream.SafeDataInput;
|
||||
import it.cavallium.stream.SafeDataOutput;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class NullableStringSerializer implements DataSerializer<NullableString> {
|
||||
|
||||
public static final NullableStringSerializer INSTANCE = new NullableStringSerializer();
|
||||
@ -27,7 +29,7 @@ public class NullableStringSerializer implements DataSerializer<NullableString>
|
||||
if (!isPresent) {
|
||||
return NullableString.empty();
|
||||
} else {
|
||||
return NullableString.of(dataInput.readUTF());
|
||||
return NullableString.of(dataInput.readShortText(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Simple {@link InputStream} implementation that exposes currently
|
||||
* available content of a {@link ByteBuffer}.
|
||||
*/
|
||||
public class ByteBufferBackedInputStream extends InputStream {
|
||||
protected final ByteBuffer _b;
|
||||
|
||||
public ByteBufferBackedInputStream(ByteBuffer buf) { _b = buf; }
|
||||
|
||||
@Override public int available() { return _b.remaining(); }
|
||||
|
||||
@Override
|
||||
public int read() { return _b.hasRemaining() ? (_b.get() & 0xFF) : -1; }
|
||||
|
||||
@Override
|
||||
public int read(byte @NotNull [] bytes, int off, int len) {
|
||||
if (!_b.hasRemaining()) return -1;
|
||||
len = Math.min(len, _b.remaining());
|
||||
_b.get(bytes, off, len);
|
||||
return len;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
|
||||
public interface DataInputOutput extends DataInput, DataOutput {
|
||||
|
||||
DataInput getIn();
|
||||
|
||||
DataOutput getOut();
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DataInputOutputImpl implements DataInputOutput {
|
||||
|
||||
private final DataInput in;
|
||||
private final DataOutput out;
|
||||
|
||||
public DataInputOutputImpl(DataInput in, DataOutput out) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataInput getIn() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOutput getOut() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFully(byte @NotNull [] bytes) throws IOException {
|
||||
in.readFully(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFully(byte @NotNull [] bytes, int i, int i1) throws IOException {
|
||||
in.readFully(bytes, i, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int skipBytes(int i) throws IOException {
|
||||
return in.skipBytes(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readBoolean() throws IOException {
|
||||
return in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() throws IOException {
|
||||
return in.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUnsignedByte() throws IOException {
|
||||
return in.readUnsignedByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public short readShort() throws IOException {
|
||||
return in.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUnsignedShort() throws IOException {
|
||||
return in.readUnsignedShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char readChar() throws IOException {
|
||||
return in.readChar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() throws IOException {
|
||||
return in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() throws IOException {
|
||||
return in.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readFloat() throws IOException {
|
||||
return in.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readDouble() throws IOException {
|
||||
return in.readDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readLine() throws IOException {
|
||||
return in.readLine();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String readUTF() throws IOException {
|
||||
return in.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int i) throws IOException {
|
||||
out.write(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte @NotNull [] bytes) throws IOException {
|
||||
out.write(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte @NotNull [] bytes, int i, int i1) throws IOException {
|
||||
out.write(bytes, i, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBoolean(boolean b) throws IOException {
|
||||
out.writeBoolean(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeByte(int i) throws IOException {
|
||||
out.writeByte(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShort(int i) throws IOException {
|
||||
out.writeShort(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChar(int i) throws IOException {
|
||||
out.writeChar(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeInt(int i) throws IOException {
|
||||
out.writeInt(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLong(long l) throws IOException {
|
||||
out.writeLong(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFloat(float v) throws IOException {
|
||||
out.writeFloat(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDouble(double v) throws IOException {
|
||||
out.writeDouble(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(@NotNull String s) throws IOException {
|
||||
out.writeBytes(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChars(@NotNull String s) throws IOException {
|
||||
out.writeChars(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeUTF(@NotNull String s) throws IOException {
|
||||
out.writeUTF(s);
|
||||
}
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DataInputOutputStream extends DataOutputStream implements DataInputOutput {
|
||||
|
||||
private final DataInputStream in;
|
||||
|
||||
public DataInputOutputStream(DataInputStream in, DataOutputStream out) {
|
||||
super(out);
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataInputStream getIn() {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOutputStream getOut() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFully(byte @NotNull [] bytes) throws IOException {
|
||||
in.readFully(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFully(byte @NotNull [] bytes, int i, int i1) throws IOException {
|
||||
in.readFully(bytes, i, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int skipBytes(int i) throws IOException {
|
||||
return in.skipBytes(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readBoolean() throws IOException {
|
||||
return in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() throws IOException {
|
||||
return in.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUnsignedByte() throws IOException {
|
||||
return in.readUnsignedByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public short readShort() throws IOException {
|
||||
return in.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUnsignedShort() throws IOException {
|
||||
return in.readUnsignedShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char readChar() throws IOException {
|
||||
return in.readChar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() throws IOException {
|
||||
return in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() throws IOException {
|
||||
return in.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readFloat() throws IOException {
|
||||
return in.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readDouble() throws IOException {
|
||||
return in.readDouble();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public String readLine() throws IOException {
|
||||
return in.readLine();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String readUTF() throws IOException {
|
||||
return in.readUTF();
|
||||
}
|
||||
}
|
@ -31,13 +31,13 @@ import java.nio.charset.Charset;
|
||||
public class SafeByteArrayInputStream extends SafeMeasurableInputStream implements SafeRepositionableStream {
|
||||
|
||||
/** The array backing the input stream. */
|
||||
public byte[] array;
|
||||
public final byte[] array;
|
||||
|
||||
/** The first valid entry. */
|
||||
public int offset;
|
||||
public final int offset;
|
||||
|
||||
/** The number of valid bytes in {@link #array} starting from {@link #offset}. */
|
||||
public int length;
|
||||
public final int length;
|
||||
|
||||
/** The current position as a distance from {@link #offset}. */
|
||||
private int position;
|
||||
@ -81,6 +81,9 @@ public class SafeByteArrayInputStream extends SafeMeasurableInputStream implemen
|
||||
|
||||
@Override
|
||||
public void mark(final int dummy) {
|
||||
if (dummy < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
mark = position;
|
||||
}
|
||||
|
||||
@ -113,7 +116,7 @@ public class SafeByteArrayInputStream extends SafeMeasurableInputStream implemen
|
||||
*/
|
||||
|
||||
@Override
|
||||
public int read(final byte b[], final int offset, final int length) {
|
||||
public int read(final byte[] b, final int offset, final int length) {
|
||||
if (this.length == this.position) return length == 0 ? 0 : -1;
|
||||
final int n = Math.min(length, this.length - this.position);
|
||||
System.arraycopy(array, this.offset + this.position, b, offset, n);
|
||||
|
@ -16,9 +16,15 @@
|
||||
|
||||
package it.cavallium.stream;
|
||||
|
||||
import it.unimi.dsi.fastutil.Arrays;
|
||||
import it.cavallium.buffer.IgnoreCoverage;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteArrays;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HexFormat;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.util.Objects.checkFromToIndex;
|
||||
|
||||
/** Simple, fast byte-array output stream that exposes the backing array.
|
||||
*
|
||||
* <p>{@link java.io.ByteArrayOutputStream} is nice, but to get its content you
|
||||
@ -36,9 +42,13 @@ public class SafeByteArrayOutputStream extends SafeMeasurableOutputStream implem
|
||||
|
||||
/** The array backing the output stream. */
|
||||
public static final int DEFAULT_INITIAL_CAPACITY = 16;
|
||||
private static final HexFormat HEX = HexFormat.of();
|
||||
private static final int MAX_PREVIEW_LENGTH = 128;
|
||||
private final boolean wrapped;
|
||||
private final int initialPosition;
|
||||
private final int initialLength;
|
||||
private final int wrappedFrom;
|
||||
private final int wrappedTo;
|
||||
|
||||
/** The array backing the output stream. */
|
||||
public byte[] array;
|
||||
@ -47,7 +57,7 @@ public class SafeByteArrayOutputStream extends SafeMeasurableOutputStream implem
|
||||
public int length;
|
||||
|
||||
/** The current writing position. */
|
||||
private int position;
|
||||
private int arrayPosition;
|
||||
|
||||
/** Creates a new array output stream with an initial capacity of {@link #DEFAULT_INITIAL_CAPACITY} bytes. */
|
||||
public SafeByteArrayOutputStream() {
|
||||
@ -61,19 +71,17 @@ public class SafeByteArrayOutputStream extends SafeMeasurableOutputStream implem
|
||||
public SafeByteArrayOutputStream(final int initialCapacity) {
|
||||
array = new byte[initialCapacity];
|
||||
wrapped = false;
|
||||
initialPosition = 0;
|
||||
initialLength = 0;
|
||||
initialPosition = wrappedFrom = length = initialLength = 0;
|
||||
wrappedTo = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/** Creates a new array output stream wrapping a given byte array.
|
||||
*
|
||||
* @param a the byte array to wrap.
|
||||
*/
|
||||
@IgnoreCoverage
|
||||
public SafeByteArrayOutputStream(final byte[] a) {
|
||||
array = a;
|
||||
wrapped = true;
|
||||
initialPosition = 0;
|
||||
initialLength = a.length;
|
||||
this(a, 0, a.length);
|
||||
}
|
||||
|
||||
/** Creates a new array output stream wrapping a given byte array.
|
||||
@ -81,19 +89,22 @@ public class SafeByteArrayOutputStream extends SafeMeasurableOutputStream implem
|
||||
* @param a the byte array to wrap.
|
||||
*/
|
||||
public SafeByteArrayOutputStream(final byte[] a, int from, int to) {
|
||||
Arrays.ensureFromTo(a.length, from, to);
|
||||
checkFromToIndex(from, to, a.length);
|
||||
wrapped = true;
|
||||
array = a;
|
||||
initialPosition = from;
|
||||
initialLength = to;
|
||||
position = from;
|
||||
length = to - from;
|
||||
initialPosition = wrappedFrom = arrayPosition = from;
|
||||
initialLength = length = to - from;
|
||||
wrappedTo = to;
|
||||
}
|
||||
|
||||
private void ensureWrappedBounds(int fromArrayPosition, int toArrayPosition) {
|
||||
Objects.checkFromToIndex(fromArrayPosition - wrappedFrom, toArrayPosition - wrappedFrom, wrappedTo - wrappedFrom);
|
||||
}
|
||||
|
||||
/** Marks this array output stream as empty. */
|
||||
public void reset() {
|
||||
length = initialLength;
|
||||
position = initialPosition;
|
||||
arrayPosition = initialPosition;
|
||||
}
|
||||
|
||||
/** Ensures that the length of the backing array is equal to {@link #length}. */
|
||||
@ -109,43 +120,55 @@ public class SafeByteArrayOutputStream extends SafeMeasurableOutputStream implem
|
||||
|
||||
@Override
|
||||
public void write(final int b) {
|
||||
if (position >= array.length) {
|
||||
if (wrapped) {
|
||||
throw new ArrayIndexOutOfBoundsException(position);
|
||||
} else {
|
||||
array = ByteArrays.grow(array, position + 1, length);
|
||||
}
|
||||
if (wrapped) {
|
||||
ensureWrappedBounds(arrayPosition, arrayPosition + 1);
|
||||
} else if (arrayPosition >= array.length) {
|
||||
array = ByteArrays.grow(array, arrayPosition + 1, length);
|
||||
}
|
||||
array[position++] = (byte)b;
|
||||
if (length < position) length = position;
|
||||
array[arrayPosition++] = (byte)b;
|
||||
if (length < arrayPosition) length = arrayPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final byte[] b, final int off, final int len) {
|
||||
ByteArrays.ensureOffsetLength(b, off, len);
|
||||
if (wrapped) {
|
||||
ensureWrappedBounds(arrayPosition, arrayPosition + len);
|
||||
}
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
growBy(len);
|
||||
System.arraycopy(b, off, array, position, len);
|
||||
if (position + len > length) length = position += len;
|
||||
System.arraycopy(b, off, array, arrayPosition, len);
|
||||
if (arrayPosition + len > length) length = arrayPosition += len;
|
||||
}
|
||||
|
||||
private void growBy(int len) {
|
||||
if (position + len > array.length) {
|
||||
if (wrapped) {
|
||||
ensureWrappedBounds(arrayPosition, arrayPosition + len);
|
||||
}
|
||||
if (arrayPosition + len > array.length) {
|
||||
if (wrapped) {
|
||||
throw new ArrayIndexOutOfBoundsException(position + len - 1);
|
||||
throw new ArrayIndexOutOfBoundsException(arrayPosition + len - 1);
|
||||
} else {
|
||||
array = ByteArrays.grow(array, position + len, position);
|
||||
array = ByteArrays.grow(array, arrayPosition + len, arrayPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void position(final long newPosition) {
|
||||
position = (int)newPosition;
|
||||
if (wrapped) {
|
||||
arrayPosition = (int) (newPosition + wrappedFrom);
|
||||
} else {
|
||||
arrayPosition = (int)newPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long position() {
|
||||
return position;
|
||||
if (wrapped) {
|
||||
return arrayPosition - wrappedFrom;
|
||||
} else {
|
||||
return arrayPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -157,6 +180,31 @@ public class SafeByteArrayOutputStream extends SafeMeasurableOutputStream implem
|
||||
* This method copies the array
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
return java.util.Arrays.copyOf(array, length);
|
||||
if (wrapped) {
|
||||
return Arrays.copyOfRange(array, wrappedFrom, wrappedTo);
|
||||
} else {
|
||||
return java.util.Arrays.copyOf(array, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SafeByteArrayOutputStream[" + toHexPreview() + "]";
|
||||
}
|
||||
|
||||
private String toHexPreview() {
|
||||
int len;
|
||||
int from;
|
||||
String prefix;
|
||||
if (wrapped) {
|
||||
prefix = "(wrapped from " + wrappedFrom + " to " + wrappedTo + ") ";
|
||||
from = wrappedFrom;
|
||||
len = wrappedTo - wrappedFrom;
|
||||
} else {
|
||||
prefix = "";
|
||||
from = 0;
|
||||
len = length;
|
||||
}
|
||||
return prefix + HEX.formatHex(this.array, from, (Math.min(len, MAX_PREVIEW_LENGTH) + from)) + ((len > MAX_PREVIEW_LENGTH) ? "..." : "");
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package it.cavallium.stream;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.DataInput;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -142,5 +144,10 @@ public interface SafeDataInput extends Closeable, DataInput {
|
||||
@Deprecated
|
||||
String readLine();
|
||||
|
||||
@Deprecated
|
||||
@NotNull String readUTF();
|
||||
|
||||
@NotNull String readShortText(Charset charset);
|
||||
|
||||
@NotNull String readMediumText(Charset charset);
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ package it.cavallium.stream;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import it.cavallium.buffer.IgnoreCoverage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SafeDataInputStream extends SafeFilterInputStream implements SafeDataInput {
|
||||
@ -41,21 +43,11 @@ public class SafeDataInputStream extends SafeFilterInputStream implements SafeDa
|
||||
super(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* working data initialized on demand by readUTF
|
||||
*/
|
||||
private byte[] bytearr;
|
||||
|
||||
@Override
|
||||
public final int read(byte[] b) {
|
||||
public final int read(byte @NotNull[] b) {
|
||||
return in.read(b, 0, b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int read(byte[] b, int off, int len) {
|
||||
return in.read(b, off, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* See the general contract of the {@code readFully}
|
||||
* method of {@code DataInput}.
|
||||
@ -125,11 +117,6 @@ public class SafeDataInputStream extends SafeFilterInputStream implements SafeDa
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString(int length, Charset charset) {
|
||||
return in.readString(length, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* See the general contract of the {@code readBoolean}
|
||||
* method of {@code DataInput}.
|
||||
@ -349,78 +336,11 @@ public class SafeDataInputStream extends SafeFilterInputStream implements SafeDa
|
||||
return Double.longBitsToDouble(readLong());
|
||||
}
|
||||
|
||||
private char[] lineBuffer;
|
||||
|
||||
/**
|
||||
* See the general contract of the {@code readLine}
|
||||
* method of {@code DataInput}.
|
||||
* <p>
|
||||
* Bytes
|
||||
* for this operation are read from the contained
|
||||
* input stream.
|
||||
*
|
||||
* @deprecated This method does not properly convert bytes to characters.
|
||||
* As of JDK 1.1, the preferred way to read lines of text is via the
|
||||
* {@code BufferedReader.readLine()} method. Programs that use the
|
||||
* {@code DataInputStream} class to read lines can be converted to use
|
||||
* the {@code BufferedReader} class by replacing code of the form:
|
||||
* <blockquote><pre>
|
||||
* DataInputStream d = new DataInputStream(in);
|
||||
* </pre></blockquote>
|
||||
* with:
|
||||
* <blockquote><pre>
|
||||
* BufferedReader d
|
||||
* = new BufferedReader(new InputStreamReader(in));
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @return the next line of text from this input stream.
|
||||
* @see java.io.BufferedReader#readLine()
|
||||
* @see SafeFilterInputStream#in
|
||||
*/
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
@Deprecated
|
||||
public final String readLine() {
|
||||
char[] buf = lineBuffer;
|
||||
|
||||
if (buf == null) {
|
||||
buf = lineBuffer = new char[128];
|
||||
}
|
||||
|
||||
int room = buf.length;
|
||||
int offset = 0;
|
||||
int c;
|
||||
|
||||
loop: while (true) {
|
||||
switch (c = in.read()) {
|
||||
case -1:
|
||||
case '\n':
|
||||
break loop;
|
||||
|
||||
case '\r':
|
||||
int c2 = in.read();
|
||||
if ((c2 != '\n') && (c2 != -1)) {
|
||||
if (!(in instanceof SafePushbackInputStream)) {
|
||||
this.in = new SafePushbackInputStream(in);
|
||||
}
|
||||
((SafePushbackInputStream)in).unread(c2);
|
||||
}
|
||||
break loop;
|
||||
|
||||
default:
|
||||
if (--room < 0) {
|
||||
buf = new char[offset + 128];
|
||||
room = buf.length - offset - 1;
|
||||
System.arraycopy(lineBuffer, 0, buf, 0, offset);
|
||||
lineBuffer = buf;
|
||||
}
|
||||
buf[offset++] = (char) c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((c == -1) && (offset == 0)) {
|
||||
return null;
|
||||
}
|
||||
return String.copyValueOf(buf, 0, offset);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,40 +352,25 @@ public class SafeDataInputStream extends SafeFilterInputStream implements SafeDa
|
||||
* input stream.
|
||||
*
|
||||
* @return a Unicode string.
|
||||
* @see SafeDataInputStream#readUTF(SafeDataInputStream)
|
||||
*/
|
||||
@Deprecated
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public @NotNull String readUTF() {
|
||||
return readUTF(this);
|
||||
return readShortText(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads from the
|
||||
* stream {@code in} a representation
|
||||
* of a Unicode character string encoded in
|
||||
* <a href="DataInput.html#modified-utf-8">modified UTF-8</a> format;
|
||||
* this string of characters is then returned as a {@code String}.
|
||||
* The details of the modified UTF-8 representation
|
||||
* are exactly the same as for the {@code readUTF}
|
||||
* method of {@code DataInput}.
|
||||
*
|
||||
* @param in a data input stream.
|
||||
* @return a Unicode string.
|
||||
* @see SafeDataInputStream#readUnsignedShort()
|
||||
*/
|
||||
public static String readUTF(SafeDataInputStream in) {
|
||||
int utflen = in.readUnsignedShort();
|
||||
byte[] data;
|
||||
if (utflen <= 80) {
|
||||
if (in.bytearr == null) {
|
||||
data = in.bytearr = new byte[80];
|
||||
} else {
|
||||
data = in.bytearr;
|
||||
}
|
||||
} else {
|
||||
data = new byte[utflen];
|
||||
}
|
||||
in.readFully(data, 0, utflen);
|
||||
return new String(data, 0, utflen, StandardCharsets.UTF_8);
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public @NotNull String readShortText(Charset charset) {
|
||||
int utfLength = this.readUnsignedShort();
|
||||
return in.readString(utfLength, charset);
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public @NotNull String readMediumText(Charset charset) {
|
||||
int utfLength = this.readInt();
|
||||
return in.readString(utfLength, charset);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,10 @@
|
||||
|
||||
package it.cavallium.stream;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* The {@code SafeDataOutput} interface provides
|
||||
* for converting data from any of the Java
|
||||
@ -69,7 +73,7 @@ public interface SafeDataOutput {
|
||||
*
|
||||
* @param b the data.
|
||||
*/
|
||||
void write(byte b[]);
|
||||
void write(byte[] b);
|
||||
|
||||
/**
|
||||
* Writes {@code len} bytes from array
|
||||
@ -90,7 +94,7 @@ public interface SafeDataOutput {
|
||||
* @param off the start offset in the data.
|
||||
* @param len the number of bytes to write.
|
||||
*/
|
||||
void write(byte b[], int off, int len);
|
||||
void write(byte[] b, int off, int len);
|
||||
|
||||
/**
|
||||
* Writes a {@code boolean} value to this output stream.
|
||||
@ -359,5 +363,10 @@ public interface SafeDataOutput {
|
||||
*
|
||||
* @param s the string value to be written.
|
||||
*/
|
||||
@Deprecated
|
||||
void writeUTF(String s);
|
||||
|
||||
void writeShortText(String s, Charset charset);
|
||||
|
||||
void writeMediumText(String s, Charset charset);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
@ -44,11 +45,6 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
|
||||
*/
|
||||
protected int written;
|
||||
|
||||
/**
|
||||
* bytearr is initialized on demand by writeUTF
|
||||
*/
|
||||
private byte[] bytearr = null;
|
||||
|
||||
/**
|
||||
* Creates a new data output stream to write data to the specified
|
||||
* underlying output stream. The counter {@code written} is
|
||||
@ -326,8 +322,14 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
|
||||
* @param str a string to be written.
|
||||
* @see #writeChars(String)
|
||||
*/
|
||||
@Deprecated
|
||||
public final void writeUTF(String str) {
|
||||
var outString = str.getBytes(StandardCharsets.UTF_8);
|
||||
writeShortText(str, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShortText(String s, Charset charset) {
|
||||
var outString = s.getBytes(charset);
|
||||
if (outString.length > Short.MAX_VALUE) {
|
||||
throw new IndexOutOfBoundsException("String too long: " + outString.length + " bytes");
|
||||
}
|
||||
@ -335,7 +337,19 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
|
||||
out.write((v >>> 8) & 0xFF);
|
||||
out.write((v) & 0xFF);
|
||||
out.write(outString);
|
||||
incCount(2 + outString.length);
|
||||
incCount(Short.BYTES + outString.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeMediumText(String s, Charset charset) {
|
||||
var outString = s.getBytes(charset);
|
||||
var v = outString.length;
|
||||
out.write((v >>> 24) & 0xFF);
|
||||
out.write((v >>> 16) & 0xFF);
|
||||
out.write((v >>> 8) & 0xFF);
|
||||
out.write((v) & 0xFF);
|
||||
out.write(outString);
|
||||
incCount(Integer.BYTES + outString.length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,8 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import it.cavallium.buffer.IgnoreCoverage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
@ -23,7 +26,7 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
/**
|
||||
* The input stream to be filtered.
|
||||
*/
|
||||
protected volatile SafeInputStream in;
|
||||
protected final SafeInputStream in;
|
||||
|
||||
/**
|
||||
* Creates a {@code FilterInputStream}
|
||||
@ -54,6 +57,7 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
* stream is reached.
|
||||
* @see SafeFilterInputStream#in
|
||||
*/
|
||||
@IgnoreCoverage
|
||||
public int read() {
|
||||
return in.read();
|
||||
}
|
||||
@ -77,7 +81,8 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
* the stream has been reached.
|
||||
* @see SafeFilterInputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte b[]) {
|
||||
@IgnoreCoverage
|
||||
public int read(byte @NotNull [] b) {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
@ -102,7 +107,8 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
* {@code b.length - off}
|
||||
* @see SafeFilterInputStream#in
|
||||
*/
|
||||
public int read(byte b[], int off, int len) {
|
||||
@IgnoreCoverage
|
||||
public final int read(byte[] b, int off, int len) {
|
||||
return in.read(b, off, len);
|
||||
}
|
||||
|
||||
@ -118,7 +124,8 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
* @param n the number of bytes to be skipped.
|
||||
* @return the actual number of bytes skipped.
|
||||
*/
|
||||
public long skip(long n) {
|
||||
@IgnoreCoverage
|
||||
public final long skip(long n) {
|
||||
return in.skip(n);
|
||||
}
|
||||
|
||||
@ -134,7 +141,8 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
* @return an estimate of the number of bytes that can be read (or skipped
|
||||
* over) from this input stream without blocking.
|
||||
*/
|
||||
public int available() {
|
||||
@IgnoreCoverage
|
||||
public final int available() {
|
||||
return in.available();
|
||||
}
|
||||
|
||||
@ -146,6 +154,7 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
*
|
||||
* @see SafeFilterInputStream#in
|
||||
*/
|
||||
@IgnoreCoverage
|
||||
public void close() {
|
||||
in.close();
|
||||
}
|
||||
@ -166,6 +175,7 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
* @see SafeFilterInputStream#in
|
||||
* @see SafeFilterInputStream#reset()
|
||||
*/
|
||||
@IgnoreCoverage
|
||||
public void mark(int readlimit) {
|
||||
in.mark(readlimit);
|
||||
}
|
||||
@ -189,6 +199,7 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
* @see SafeFilterInputStream#in
|
||||
* @see SafeFilterInputStream#mark(int)
|
||||
*/
|
||||
@IgnoreCoverage
|
||||
public void reset() {
|
||||
in.reset();
|
||||
}
|
||||
@ -206,10 +217,12 @@ public class SafeFilterInputStream extends SafeInputStream {
|
||||
* @see java.io.InputStream#mark(int)
|
||||
* @see java.io.InputStream#reset()
|
||||
*/
|
||||
@IgnoreCoverage
|
||||
public boolean markSupported() {
|
||||
return in.markSupported();
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
@Override
|
||||
public String readString(int length, Charset charset) {
|
||||
return in.readString(length, charset);
|
||||
|
@ -1,5 +1,8 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import it.cavallium.buffer.IgnoreCoverage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@ -20,11 +23,12 @@ public abstract class SafeInputStream extends InputStream {
|
||||
@Override
|
||||
public abstract int read();
|
||||
|
||||
public int read(byte b[]) {
|
||||
public int read(byte @NotNull [] b) {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
public int read(byte b[], int off, int len) {
|
||||
@IgnoreCoverage
|
||||
public int read(byte[] b, int off, int len) {
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
@ -34,15 +38,16 @@ public abstract class SafeInputStream extends InputStream {
|
||||
if (c == -1) {
|
||||
return -1;
|
||||
}
|
||||
b[off] = (byte)c;
|
||||
b[off] = (byte) c;
|
||||
|
||||
int i = 1;
|
||||
for (; i < len ; i++) {
|
||||
while (i < len) {
|
||||
c = read();
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
b[off + i] = (byte)c;
|
||||
b[off + i] = (byte) c;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@ -53,47 +58,49 @@ public abstract class SafeInputStream extends InputStream {
|
||||
|
||||
private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
@IgnoreCoverage
|
||||
public byte[] readNBytes(int len) {
|
||||
if (len < 0) {
|
||||
throw new IllegalArgumentException("len < 0");
|
||||
}
|
||||
|
||||
List<byte[]> bufs = null;
|
||||
List<byte[]> buffers = null;
|
||||
byte[] result = null;
|
||||
int total = 0;
|
||||
int remaining = len;
|
||||
int n;
|
||||
//noinspection NonStrictComparisonCanBeEquality
|
||||
do {
|
||||
byte[] buf = new byte[Math.min(remaining, DEFAULT_BUFFER_SIZE)];
|
||||
int nread = 0;
|
||||
int numRead = 0;
|
||||
|
||||
// read to EOF which may read more or less than buffer size
|
||||
while ((n = read(buf, nread,
|
||||
Math.min(buf.length - nread, remaining))) > 0) {
|
||||
nread += n;
|
||||
while ((n = read(buf, numRead,
|
||||
Math.min(buf.length - numRead, remaining))) > 0) {
|
||||
numRead += n;
|
||||
remaining -= n;
|
||||
}
|
||||
|
||||
if (nread > 0) {
|
||||
if (MAX_BUFFER_SIZE - total < nread) {
|
||||
if (numRead > 0) {
|
||||
if (MAX_BUFFER_SIZE - total < numRead) {
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
}
|
||||
total += nread;
|
||||
total += numRead;
|
||||
if (result == null) {
|
||||
result = buf;
|
||||
} else {
|
||||
if (bufs == null) {
|
||||
bufs = new ArrayList<>();
|
||||
bufs.add(result);
|
||||
if (buffers == null) {
|
||||
buffers = new ArrayList<>();
|
||||
buffers.add(result);
|
||||
}
|
||||
bufs.add(buf);
|
||||
buffers.add(buf);
|
||||
}
|
||||
}
|
||||
// if the last call to read returned -1 or the number of bytes
|
||||
// requested have been read then break
|
||||
} while (n >= 0 && remaining > 0);
|
||||
|
||||
if (bufs == null) {
|
||||
if (buffers == null) {
|
||||
if (result == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
@ -104,7 +111,7 @@ public abstract class SafeInputStream extends InputStream {
|
||||
result = new byte[total];
|
||||
int offset = 0;
|
||||
remaining = total;
|
||||
for (byte[] b : bufs) {
|
||||
for (byte[] b : buffers) {
|
||||
int count = Math.min(b.length, remaining);
|
||||
System.arraycopy(b, 0, result, offset, count);
|
||||
offset += count;
|
||||
@ -155,6 +162,7 @@ public abstract class SafeInputStream extends InputStream {
|
||||
public void skipNBytes(long n) {
|
||||
if (n > 0) {
|
||||
long ns = skip(n);
|
||||
//noinspection ConstantValue
|
||||
if (ns >= 0 && ns < n) { // skipped too few bytes
|
||||
// adjust number to skip
|
||||
n -= ns;
|
||||
@ -162,7 +170,7 @@ public abstract class SafeInputStream extends InputStream {
|
||||
while (n > 0 && read() != -1) {
|
||||
n--;
|
||||
}
|
||||
// if not enough skipped, then EOFE
|
||||
// if not enough skipped, then EOF E
|
||||
if (n != 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
@ -172,21 +180,18 @@ public abstract class SafeInputStream extends InputStream {
|
||||
}
|
||||
}
|
||||
|
||||
@IgnoreCoverage
|
||||
public int available() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@IgnoreCoverage
|
||||
public void close() {}
|
||||
|
||||
public void mark(int readlimit) {}
|
||||
|
||||
@IgnoreCoverage
|
||||
public void reset() {
|
||||
throw new UnsupportedOperationException("mark/reset not supported");
|
||||
}
|
||||
|
||||
public boolean markSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public long transferTo(OutputStream out) {
|
||||
Objects.requireNonNull(out, "out");
|
||||
|
@ -1,332 +0,0 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
/**
|
||||
* A {@code PushbackInputStream} adds
|
||||
* functionality to another input stream, namely
|
||||
* the ability to "push back" or "unread" bytes,
|
||||
* by storing pushed-back bytes in an internal buffer.
|
||||
* This is useful in situations where
|
||||
* it is convenient for a fragment of code
|
||||
* to read an indefinite number of data bytes
|
||||
* that are delimited by a particular byte
|
||||
* value; after reading the terminating byte,
|
||||
* the code fragment can "unread" it, so that
|
||||
* the next read operation on the input stream
|
||||
* will reread the byte that was pushed back.
|
||||
* For example, bytes representing the characters
|
||||
* constituting an identifier might be terminated
|
||||
* by a byte representing an operator character;
|
||||
* a method whose job is to read just an identifier
|
||||
* can read until it sees the operator and
|
||||
* then push the operator back to be re-read.
|
||||
*
|
||||
* @author David Connelly
|
||||
* @author Jonathan Payne
|
||||
* @since 1.0
|
||||
*/
|
||||
public class SafePushbackInputStream extends SafeFilterInputStream {
|
||||
/**
|
||||
* The pushback buffer.
|
||||
* @since 1.1
|
||||
*/
|
||||
protected byte[] buf;
|
||||
|
||||
/**
|
||||
* The position within the pushback buffer from which the next byte will
|
||||
* be read. When the buffer is empty, {@code pos} is equal to
|
||||
* {@code buf.length}; when the buffer is full, {@code pos} is
|
||||
* equal to zero.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
protected int pos;
|
||||
|
||||
/**
|
||||
* Check to make sure that this stream has not been closed
|
||||
*/
|
||||
private void ensureOpen() {
|
||||
if (in == null)
|
||||
throw new IllegalStateException("Stream closed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code PushbackInputStream}
|
||||
* with a pushback buffer of the specified {@code size},
|
||||
* and saves its argument, the input stream
|
||||
* {@code in}, for later use. Initially,
|
||||
* the pushback buffer is empty.
|
||||
*
|
||||
* @param in the input stream from which bytes will be read.
|
||||
* @param size the size of the pushback buffer.
|
||||
* @throws IllegalArgumentException if {@code size <= 0}
|
||||
* @since 1.1
|
||||
*/
|
||||
public SafePushbackInputStream(SafeInputStream in, int size) {
|
||||
super(in);
|
||||
if (size <= 0) {
|
||||
throw new IllegalArgumentException("size <= 0");
|
||||
}
|
||||
this.buf = new byte[size];
|
||||
this.pos = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code PushbackInputStream}
|
||||
* with a 1-byte pushback buffer, and saves its argument, the input stream
|
||||
* {@code in}, for later use. Initially,
|
||||
* the pushback buffer is empty.
|
||||
*
|
||||
* @param in the input stream from which bytes will be read.
|
||||
*/
|
||||
public SafePushbackInputStream(SafeInputStream in) {
|
||||
this(in, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next byte of data from this input stream. The value
|
||||
* byte is returned as an {@code int} in the range
|
||||
* {@code 0} to {@code 255}. If no byte is available
|
||||
* because the end of the stream has been reached, the value
|
||||
* {@code -1} is returned. This method blocks until input data
|
||||
* is available, the end of the stream is detected, or an exception
|
||||
* is thrown.
|
||||
*
|
||||
* <p> This method returns the most recently pushed-back byte, if there is
|
||||
* one, and otherwise calls the {@code read} method of its underlying
|
||||
* input stream and returns whatever value that method returns.
|
||||
*
|
||||
* @return the next byte of data, or {@code -1} if the end of the
|
||||
* stream has been reached.
|
||||
* or an I/O error occurs.
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public int read() {
|
||||
ensureOpen();
|
||||
if (pos < buf.length) {
|
||||
return buf[pos++] & 0xff;
|
||||
}
|
||||
return super.read();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads up to {@code len} bytes of data from this input stream into
|
||||
* an array of bytes. This method first reads any pushed-back bytes; after
|
||||
* that, if fewer than {@code len} bytes have been read then it
|
||||
* reads from the underlying input stream. If {@code len} is not zero, the method
|
||||
* blocks until at least 1 byte of input is available; otherwise, no
|
||||
* bytes are read and {@code 0} is returned.
|
||||
*
|
||||
* @param b the buffer into which the data is read.
|
||||
* @param off the start offset in the destination array {@code b}
|
||||
* @param len the maximum number of bytes read.
|
||||
* @return the total number of bytes read into the buffer, or
|
||||
* {@code -1} if there is no more data because the end of
|
||||
* the stream has been reached.
|
||||
* @throws NullPointerException If {@code b} is {@code null}.
|
||||
* @throws IndexOutOfBoundsException If {@code off} is negative,
|
||||
* {@code len} is negative, or {@code len} is greater than
|
||||
* {@code b.length - off}
|
||||
* or an I/O error occurs.
|
||||
* @see java.io.InputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte[] b, int off, int len) {
|
||||
ensureOpen();
|
||||
if (b == null) {
|
||||
throw new NullPointerException();
|
||||
} else if (off < 0 || len < 0 || len > b.length - off) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avail = buf.length - pos;
|
||||
if (avail > 0) {
|
||||
if (len < avail) {
|
||||
avail = len;
|
||||
}
|
||||
System.arraycopy(buf, pos, b, off, avail);
|
||||
pos += avail;
|
||||
off += avail;
|
||||
len -= avail;
|
||||
}
|
||||
if (len > 0) {
|
||||
len = super.read(b, off, len);
|
||||
if (len == -1) {
|
||||
return avail == 0 ? -1 : avail;
|
||||
}
|
||||
return avail + len;
|
||||
}
|
||||
return avail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes back a byte by copying it to the front of the pushback buffer.
|
||||
* After this method returns, the next byte to be read will have the value
|
||||
* {@code (byte)b}.
|
||||
*
|
||||
* @param b the {@code int} value whose low-order
|
||||
* byte is to be pushed back.
|
||||
*/
|
||||
public void unread(int b) {
|
||||
ensureOpen();
|
||||
if (pos == 0) {
|
||||
throw new IllegalStateException("Push back buffer is full");
|
||||
}
|
||||
buf[--pos] = (byte)b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes back a portion of an array of bytes by copying it to the front
|
||||
* of the pushback buffer. After this method returns, the next byte to be
|
||||
* read will have the value {@code b[off]}, the byte after that will
|
||||
* have the value {@code b[off+1]}, and so forth.
|
||||
*
|
||||
* @param b the byte array to push back.
|
||||
* @param off the start offset of the data.
|
||||
* @param len the number of bytes to push back.
|
||||
* @throws NullPointerException If {@code b} is {@code null}.
|
||||
* @since 1.1
|
||||
*/
|
||||
public void unread(byte[] b, int off, int len) {
|
||||
ensureOpen();
|
||||
if (len > pos) {
|
||||
throw new IllegalStateException("Push back buffer is full");
|
||||
}
|
||||
pos -= len;
|
||||
System.arraycopy(b, off, buf, pos, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes back an array of bytes by copying it to the front of the
|
||||
* pushback buffer. After this method returns, the next byte to be read
|
||||
* will have the value {@code b[0]}, the byte after that will have the
|
||||
* value {@code b[1]}, and so forth.
|
||||
*
|
||||
* @param b the byte array to push back
|
||||
* @throws NullPointerException If {@code b} is {@code null}.
|
||||
* @since 1.1
|
||||
*/
|
||||
public void unread(byte[] b) {
|
||||
unread(b, 0, b.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of bytes that can be read (or
|
||||
* skipped over) from this input stream without blocking by the next
|
||||
* invocation of a method for this input stream. The next invocation might be
|
||||
* the same thread or another thread. A single read or skip of this
|
||||
* many bytes will not block, but may read or skip fewer bytes.
|
||||
*
|
||||
* <p> The method returns the sum of the number of bytes that have been
|
||||
* pushed back and the value returned by {@link
|
||||
* SafeFilterInputStream#available available}.
|
||||
*
|
||||
* @return the number of bytes that can be read (or skipped over) from
|
||||
* the input stream without blocking.
|
||||
* @see SafeFilterInputStream#in
|
||||
* @see java.io.InputStream#available()
|
||||
*/
|
||||
public int available() {
|
||||
ensureOpen();
|
||||
int n = buf.length - pos;
|
||||
int avail = super.available();
|
||||
return n > (Integer.MAX_VALUE - avail)
|
||||
? Integer.MAX_VALUE
|
||||
: n + avail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips over and discards {@code n} bytes of data from this
|
||||
* input stream. The {@code skip} method may, for a variety of
|
||||
* reasons, end up skipping over some smaller number of bytes,
|
||||
* possibly zero. If {@code n} is negative, no bytes are skipped.
|
||||
*
|
||||
* <p> The {@code skip} method of {@code PushbackInputStream}
|
||||
* first skips over the bytes in the pushback buffer, if any. It then
|
||||
* calls the {@code skip} method of the underlying input stream if
|
||||
* more bytes need to be skipped. The actual number of bytes skipped
|
||||
* is returned.
|
||||
*
|
||||
* @param n {@inheritDoc}
|
||||
* @return {@inheritDoc}
|
||||
* @see SafeFilterInputStream#in
|
||||
* @see java.io.InputStream#skip(long n)
|
||||
* @since 1.2
|
||||
*/
|
||||
public long skip(long n) {
|
||||
ensureOpen();
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long pskip = buf.length - pos;
|
||||
if (pskip > 0) {
|
||||
if (n < pskip) {
|
||||
pskip = n;
|
||||
}
|
||||
pos += pskip;
|
||||
n -= pskip;
|
||||
}
|
||||
if (n > 0) {
|
||||
pskip += super.skip(n);
|
||||
}
|
||||
return pskip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this input stream supports the {@code mark} and
|
||||
* {@code reset} methods, which it does not.
|
||||
*
|
||||
* @return {@code false}, since this class does not support the
|
||||
* {@code mark} and {@code reset} methods.
|
||||
* @see java.io.InputStream#mark(int)
|
||||
* @see java.io.InputStream#reset()
|
||||
*/
|
||||
public boolean markSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the current position in this input stream.
|
||||
*
|
||||
* <p> The {@code mark} method of {@code PushbackInputStream}
|
||||
* does nothing.
|
||||
*
|
||||
* @param readlimit the maximum limit of bytes that can be read before
|
||||
* the mark position becomes invalid.
|
||||
* @see java.io.InputStream#reset()
|
||||
*/
|
||||
public void mark(int readlimit) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Repositions this stream to the position at the time the
|
||||
* {@code mark} method was last called on this input stream.
|
||||
*
|
||||
* <p> The method {@code reset} for class
|
||||
* {@code PushbackInputStream} does nothing except throw an
|
||||
* {@code IOException}.
|
||||
*
|
||||
* @see java.io.InputStream#mark(int)
|
||||
* @see java.io.IOException
|
||||
*/
|
||||
public void reset() {
|
||||
throw new UnsupportedOperationException("mark/reset not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this input stream and releases any system resources
|
||||
* associated with the stream.
|
||||
* Once the stream has been closed, further read(), unread(),
|
||||
* available(), reset(), or skip() invocations will throw an IOException.
|
||||
* Closing a previously closed stream has no effect.
|
||||
*
|
||||
*/
|
||||
public void close() {
|
||||
if (in == null)
|
||||
return;
|
||||
in.close();
|
||||
in = null;
|
||||
buf = null;
|
||||
}
|
||||
}
|
@ -1,22 +1,20 @@
|
||||
package it.cavallium.buffer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import com.google.common.primitives.Longs;
|
||||
import it.cavallium.stream.SafeByteArrayInputStream;
|
||||
import it.cavallium.stream.SafeByteArrayOutputStream;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteArrayList;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteCollections;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteList;
|
||||
import it.cavallium.stream.SafeDataOutputStream;
|
||||
import it.unimi.dsi.fastutil.bytes.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.HexFormat;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
@ -121,9 +119,10 @@ public class TestBuffer {
|
||||
|
||||
public static List<BufArg> createSubListBufs() {
|
||||
var sameSizeArgs = createPrimaryBufs().stream().filter(b -> b.initialSize > 0).map(bufArg -> new BufArg(bufArg.name + ".subList(0, same)", bufArg.b.subList(0, bufArg.initialSize), bufArg.initialSize, bufArg.initialContent)).toList();
|
||||
var sameSizeArgsBug = createPrimaryBufs().stream().filter(b -> b.initialSize > 0).map(bufArg -> new BufArg(bufArg.name + ".subList(0, same)", bufArg.b.subListForced(0, bufArg.initialSize), bufArg.initialSize, bufArg.initialContent)).toList();
|
||||
var firstHalfArgs = createPrimaryBufs().stream().filter(b -> b.initialSize > 0).map(bufArg -> new BufArg(bufArg.name + ".subList(0, half)", bufArg.b.subList(0, bufArg.initialSize/2), bufArg.initialSize/2, Arrays.copyOfRange(bufArg.initialContent, 0, bufArg.initialSize/2))).toList();
|
||||
var lastHalfArgs = createPrimaryBufs().stream().filter(b -> b.initialSize > 0).map(bufArg -> new BufArg(bufArg.name + ".subList(half, same)", bufArg.b.subList(bufArg.initialSize/2, bufArg.initialSize), bufArg.initialSize - bufArg.initialSize/2, Arrays.copyOfRange(bufArg.initialContent, bufArg.initialSize/2, bufArg.initialSize))).toList();
|
||||
return Stream.concat(Stream.concat(sameSizeArgs.stream(), firstHalfArgs.stream()), lastHalfArgs.stream()).toList();
|
||||
return Stream.concat(Stream.concat(Stream.concat(sameSizeArgs.stream(), sameSizeArgsBug.stream()), firstHalfArgs.stream()), lastHalfArgs.stream()).toList();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -407,10 +406,147 @@ public class TestBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
//todo:
|
||||
private void testBinaryOutputStream(SafeByteArrayOutputStream bos) {
|
||||
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideBufs")
|
||||
public void testBinaryInputStream(BufArg bufArg) {
|
||||
testBinaryInputStream(bufArg.b.binaryInputStream());
|
||||
}
|
||||
|
||||
//todo:
|
||||
private void testBinaryInputStream(SafeByteArrayInputStream bis) {
|
||||
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideBufs")
|
||||
public void testWriteTo(BufArg bufArg) {
|
||||
try (var safeBaOs = new SafeByteArrayOutputStream()) {
|
||||
try (var safeDaOs = new SafeDataOutputStream(safeBaOs)) {
|
||||
bufArg.b.writeTo(safeDaOs);
|
||||
}
|
||||
assertArrayEquals(bufArg.initialContent, safeBaOs.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideBufs")
|
||||
public void testEquals(BufArg bufArg) {
|
||||
var b2 = Buf.copyOf(bufArg.initialContent);
|
||||
testEquals(bufArg.b, b2);
|
||||
testEquals(b2, bufArg.b);
|
||||
}
|
||||
|
||||
private void testEquals(Buf a, Buf b) {
|
||||
assertEquals(a, b);
|
||||
assertArrayEquals(a.toByteArray(), b.toByteArray());
|
||||
//noinspection SimplifiableAssertion
|
||||
assertTrue(a.equals(b.subListForced(0, b.size())));
|
||||
//noinspection SimplifiableAssertion
|
||||
assertTrue(a.equals(new ByteArrayList(b)));
|
||||
//noinspection SimplifiableAssertion
|
||||
assertTrue(a.equals(new ArrayList<>(b)));
|
||||
assertTrue(a.equals(0, b, 0, a.size()));
|
||||
assertTrue(a.equals(0, b.toByteArray(), 0, a.size()));
|
||||
assertTrue(a.equals(0, b, 0, a.size() / 2));
|
||||
assertTrue(a.equals(0, b.toByteArray(), 0, a.size() / 2));
|
||||
if (a.size() > 5) {
|
||||
assertTrue(a.equals(5, b, 5, a.size() - 5));
|
||||
assertTrue(a.equals(5, b.toByteArray(), 5, a.size() - 5));
|
||||
assertTrue(a.equals(5, b, 5, 0));
|
||||
assertTrue(a.equals(5, b.toByteArray(), 5, 0));
|
||||
assertFalse(a.equals(0, new byte[1], 100, 1));
|
||||
}
|
||||
if (a.size() >= 10) {
|
||||
assertTrue(a.equals(5, b, 5, a.size() - 5 - 3));
|
||||
assertTrue(a.equals(5, b.toByteArray(), 5, a.size() - 5 - 3));
|
||||
assertFalse(a.equals(5, b.toByteArray(), 5, a.size()));
|
||||
}
|
||||
assertFalse(a.equals(a.size(), b, 0, 1));
|
||||
assertFalse(a.equals(a.size(), b.toByteArray(), 0, 1));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideBufs")
|
||||
public void testCompareTo(BufArg bufArg) {
|
||||
if (bufArg.initialSize > 0) {
|
||||
var bigger = Arrays.copyOf(bufArg.initialContent, bufArg.initialSize + 1);
|
||||
assertTrue(bufArg.b.compareTo(Buf.wrap(bigger)) < 0);
|
||||
assertTrue(bufArg.b.compareTo(Buf.wrap(bigger).subListForced(0, bigger.length)) < 0);
|
||||
assertTrue(bufArg.b.compareTo(new ByteArrayList(bigger)) < 0);
|
||||
var smaller = Arrays.copyOf(bufArg.initialContent, bufArg.initialSize - 1);
|
||||
assertTrue(bufArg.b.compareTo(Buf.wrap(smaller)) > 0);
|
||||
var equal = Arrays.copyOf(bufArg.initialContent, bufArg.initialSize);
|
||||
assertEquals(0, bufArg.b.compareTo(Buf.wrap(equal)));
|
||||
var bigger2 = Arrays.copyOf(bufArg.initialContent, bufArg.initialSize);
|
||||
if (bigger2[bigger2.length - 1] < 127) {
|
||||
bigger2[bigger2.length - 1]++;
|
||||
assertTrue(bufArg.b.compareTo(Buf.wrap(bigger2)) < 0);
|
||||
}
|
||||
var smaller2 = Arrays.copyOf(bufArg.initialContent, bufArg.initialSize);
|
||||
if (smaller2[smaller2.length - 1] > 0) {
|
||||
smaller2[smaller2.length - 1]--;
|
||||
assertTrue(bufArg.b.compareTo(Buf.wrap(smaller2)) > 0);
|
||||
};
|
||||
assertTrue(bufArg.b.compareTo(Buf.create()) > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideBufs")
|
||||
public void testIterator(BufArg bufArg) {
|
||||
var it1 = ByteList.of(bufArg.initialContent).iterator();
|
||||
var it2 = bufArg.b.iterator();
|
||||
var it3 = bufArg.b.listIterator();
|
||||
var it4 = bufArg.b.iterator();
|
||||
while (it1.hasNext() && it2.hasNext() && it3.hasNext() && it4.hasNext()) {
|
||||
Byte a = it1.nextByte();
|
||||
byte b = it4.nextByte();
|
||||
//noinspection deprecation
|
||||
byte b2 = it2.next();
|
||||
//noinspection deprecation
|
||||
byte b3 = it3.next();
|
||||
//noinspection deprecation
|
||||
it3.previous();
|
||||
byte b4 = it3.nextByte();
|
||||
assertEquals(a, b);
|
||||
assertEquals(a, b2);
|
||||
assertEquals(a, b3);
|
||||
assertEquals(a, b4);
|
||||
}
|
||||
assertFalse(it1.hasNext());
|
||||
assertFalse(it2.hasNext());
|
||||
assertFalse(it3.hasNext());
|
||||
assertFalse(it4.hasNext());
|
||||
|
||||
// Test list iterator
|
||||
{
|
||||
var fei = bufArg.b.iterator();
|
||||
LongAdder adder = new LongAdder();
|
||||
bufArg.b.listIterator().forEachRemaining(b -> {
|
||||
assertEquals(fei.nextByte(), b);
|
||||
adder.increment();
|
||||
});
|
||||
assertEquals(bufArg.initialSize, adder.sum());
|
||||
}
|
||||
|
||||
// Test list iterator with initial index
|
||||
if (bufArg.initialSize > 0) {
|
||||
assertEquals(bufArg.b.getByte(bufArg.initialSize - 1), bufArg.b.listIterator(bufArg.initialSize).previousByte());
|
||||
}
|
||||
|
||||
// Test spliterator
|
||||
//noinspection SimplifyStreamApiCallChains
|
||||
assertArrayEquals(bufArg.initialContent, new ByteArrayList(StreamSupport.stream(bufArg.b.spliterator(), true).toList()).toByteArray());
|
||||
//noinspection SimplifyStreamApiCallChains
|
||||
assertArrayEquals(bufArg.initialContent, new ByteArrayList(StreamSupport.stream(bufArg.b.spliterator(), false).peek(c -> {}).toList()).toByteArray());
|
||||
assertArrayEquals(bufArg.initialContent, new ByteArrayList(Spliterators.iterator(bufArg.b.spliterator())).toByteArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testByteListBufConstructor() {
|
||||
ByteListBuf blb1 = new ByteListBuf();
|
||||
@ -440,6 +576,5 @@ public class TestBuffer {
|
||||
assertEquals(blb1, blb6);
|
||||
assertEquals(blb1, blb7);
|
||||
assertEquals(blb1, blb8);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,264 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import it.cavallium.buffer.Buf;
|
||||
import it.cavallium.buffer.BufDataInput;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public class TestInput {
|
||||
|
||||
public static final byte[] DATA = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
|
||||
public static Stream<SafeInputStream> provideStreams() {
|
||||
var dataLarge = new byte[] {-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
|
||||
return Stream.of(
|
||||
new SafeDataInputStream(new SafeByteArrayInputStream(DATA)),
|
||||
new SafeByteArrayInputStream(DATA),
|
||||
BufDataInput.create(Buf.wrap(DATA)),
|
||||
BufDataInput.create(Buf.wrap(dataLarge).subList(2, 12)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBufDataInputValidity() {
|
||||
var bdi = BufDataInput.create(Buf.wrap((byte) 1, (byte) 2, (byte) 3, (byte) 4));
|
||||
assertThrows(UnsupportedOperationException.class, () -> bdi.mark(1));
|
||||
assertThrows(UnsupportedOperationException.class, bdi::reset);
|
||||
//noinspection deprecation
|
||||
assertDoesNotThrow(bdi::close);
|
||||
assertFalse(bdi.markSupported());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws IOException {
|
||||
String data = "Ciaoç\uD83D\uDC6A";
|
||||
var shortBaos = new ByteArrayOutputStream();
|
||||
var medBaos = new ByteArrayOutputStream();
|
||||
var shortDaos = new DataOutputStream(shortBaos);
|
||||
var medDaos = new DataOutputStream(medBaos);
|
||||
var sbytes = data.getBytes(StandardCharsets.UTF_8);
|
||||
shortDaos.writeShort(sbytes.length);
|
||||
shortDaos.write(sbytes);
|
||||
medDaos.writeInt(sbytes.length);
|
||||
medDaos.write(sbytes);
|
||||
var shortBytes = shortBaos.toByteArray();
|
||||
var medBytes = medBaos.toByteArray();
|
||||
var bdi = BufDataInput.create(Buf.wrap(shortBytes));
|
||||
//noinspection deprecation
|
||||
assertEquals(data, bdi.readUTF());
|
||||
var bdi2 = BufDataInput.create(Buf.wrap(shortBytes).subList(Short.BYTES, shortBytes.length));
|
||||
assertEquals(data, bdi2.readString(sbytes.length, StandardCharsets.UTF_8));
|
||||
var bdi3 = BufDataInput.create(Buf.wrap(shortBytes));
|
||||
assertEquals(data, bdi3.readShortText(StandardCharsets.UTF_8));
|
||||
var bdi4 = BufDataInput.create(Buf.wrap(medBytes));
|
||||
assertEquals(data, bdi4.readMediumText(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadTypes() throws IOException {
|
||||
var baos = new ByteArrayOutputStream();
|
||||
var daos = new DataOutputStream(baos);
|
||||
daos.write(10);
|
||||
daos.writeByte(10);
|
||||
daos.writeShort(10);
|
||||
daos.writeByte(255);
|
||||
daos.writeShort(50000);
|
||||
daos.writeChar(10);
|
||||
daos.writeUTF("123");
|
||||
daos.writeInt(10);
|
||||
daos.writeLong(10);
|
||||
daos.writeFloat(10);
|
||||
daos.writeDouble(10);
|
||||
daos.writeBoolean(true);
|
||||
var bytes1 = new byte[] {1, 2, 3, 4};
|
||||
daos.write(bytes1);
|
||||
daos.write(0);
|
||||
daos.write(0);
|
||||
daos.write(0);
|
||||
daos.write("Ciao".getBytes(StandardCharsets.UTF_8));
|
||||
{
|
||||
var writeBuffer = new byte[7];
|
||||
var v = (1L << 52) - 1;
|
||||
writeBuffer[0] = (byte)(v >> 48 & 0xf);
|
||||
writeBuffer[1] = (byte)(v >> 40 & 0xff);
|
||||
writeBuffer[2] = (byte)(v >> 32 & 0xff);
|
||||
writeBuffer[3] = (byte)(v >> 24 & 0xff);
|
||||
writeBuffer[4] = (byte)(v >> 16 & 0xff);
|
||||
writeBuffer[5] = (byte)(v >> 8 & 0xff);
|
||||
writeBuffer[6] = (byte)(v & 0xff);
|
||||
daos.write(writeBuffer);
|
||||
}
|
||||
daos.writeShort(4);
|
||||
daos.write("Ciao".getBytes(StandardCharsets.UTF_8));
|
||||
daos.writeInt(4);
|
||||
daos.write("Ciao".getBytes(StandardCharsets.UTF_8));
|
||||
daos.write(1);
|
||||
daos.write(2);
|
||||
var initialArray = baos.toByteArray();
|
||||
|
||||
var bdi = BufDataInput.create(Buf.wrap(initialArray));
|
||||
assertEquals(10, bdi.read());
|
||||
assertEquals(10, bdi.readByte());
|
||||
assertEquals(10, bdi.readShort());
|
||||
assertEquals(255, bdi.readUnsignedByte());
|
||||
assertEquals(50000, bdi.readUnsignedShort());
|
||||
assertEquals(10, bdi.readChar());
|
||||
//noinspection deprecation
|
||||
assertEquals("123", bdi.readUTF());
|
||||
assertEquals(10, bdi.readInt());
|
||||
assertEquals(10, bdi.readLong());
|
||||
assertEquals(10, bdi.readFloat());
|
||||
assertEquals(10, bdi.readDouble());
|
||||
assertTrue(bdi.readBoolean());
|
||||
{
|
||||
var in = new byte[4];
|
||||
bdi.readFully(in);
|
||||
assertArrayEquals(bytes1, in);
|
||||
}
|
||||
bdi.skipNBytes(1);
|
||||
assertEquals(1, bdi.skipBytes(1));
|
||||
assertEquals(1, bdi.skip(1));
|
||||
assertEquals("Ciao", bdi.readString(4, StandardCharsets.UTF_8));
|
||||
assertEquals((1L << 52) - 1, bdi.readInt52());
|
||||
assertEquals("Ciao", bdi.readShortText(StandardCharsets.UTF_8));
|
||||
assertEquals("Ciao", bdi.readMediumText(StandardCharsets.UTF_8));
|
||||
{
|
||||
var buf = new byte[1];
|
||||
assertEquals(1, bdi.read(buf));
|
||||
assertArrayEquals(new byte[] {1}, buf);
|
||||
assertEquals(1, bdi.read(buf, 0, 1));
|
||||
assertArrayEquals(new byte[] {2}, buf);
|
||||
}
|
||||
{
|
||||
var bdi1 = BufDataInput.create(Buf.create());
|
||||
assertEquals(0, bdi1.skip(1));
|
||||
assertEquals(0, bdi1.skipBytes(1));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> bdi1.readString(10, StandardCharsets.UTF_8));
|
||||
var in = new byte[4];
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> bdi1.readFully(in));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> bdi1.readFully(in, 0, -1));
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readBoolean);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readByte);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readShort);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readInt);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readInt52);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readLong);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readFloat);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readChar);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readDouble);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readUnsignedShort);
|
||||
assertThrows(IndexOutOfBoundsException.class, bdi1::readUnsignedByte);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideStreams")
|
||||
public void testSkip(SafeInputStream is) {
|
||||
assertEquals(10, is.skip(15));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideStreams")
|
||||
public void testSkipNBytes(SafeInputStream is) {
|
||||
assertDoesNotThrow(() -> is.skipNBytes(10));
|
||||
assertThrows(Exception.class, () -> is.skipNBytes(1));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideStreams")
|
||||
public void testRead(SafeInputStream is) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertEquals(i, is.read());
|
||||
}
|
||||
assertEquals(-1, is.read());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideStreams")
|
||||
public void testReadSmaller(SafeInputStream is) {
|
||||
byte[] data = new byte[9];
|
||||
assertEquals(9, is.read(data));
|
||||
assertArrayEquals(Arrays.copyOf(DATA, 9), data);
|
||||
assertEquals(9, is.read());
|
||||
assertEquals(-1, is.read());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideStreams")
|
||||
public void testReadBigger(SafeInputStream is) {
|
||||
byte[] data = new byte[11];
|
||||
assertEquals(10, is.read(data));
|
||||
assertArrayEquals(Arrays.copyOf(DATA, 11), data);
|
||||
assertEquals(-1, is.read());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideStreams")
|
||||
public void testReadExact(SafeInputStream is) {
|
||||
byte[] data = new byte[10];
|
||||
assertEquals(10, is.read(data));
|
||||
assertArrayEquals(DATA, data);
|
||||
assertEquals(-1, is.read());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideStreams")
|
||||
public void testPosition(SafeInputStream is) {
|
||||
if (is instanceof SafeByteArrayInputStream bis) {
|
||||
assertEquals(10, bis.available());
|
||||
assertEquals(10, bis.length());
|
||||
assertEquals(0, bis.position());
|
||||
assertEquals(0, bis.read());
|
||||
assertEquals(1, bis.position());
|
||||
assertEquals(1, bis.read());
|
||||
assertEquals(2, bis.position());
|
||||
assertEquals(2, bis.read());
|
||||
assertEquals(3, bis.position());
|
||||
assertEquals(7, bis.skip(1000));
|
||||
assertEquals(-1, bis.read());
|
||||
assertEquals(10, bis.position());
|
||||
bis.position(0);
|
||||
assertEquals(0, bis.position());
|
||||
assertEquals(0, bis.read());
|
||||
assertEquals(1, bis.position());
|
||||
assertEquals(9, bis.available());
|
||||
assertEquals(10, bis.length());
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideStreams")
|
||||
public void testMark(SafeInputStream is) {
|
||||
if (is.markSupported()) {
|
||||
is.mark(1);
|
||||
assertEquals(0, is.read());
|
||||
assertEquals(1, is.read());
|
||||
is.reset();
|
||||
assertEquals(0, is.read());
|
||||
assertEquals(1, is.read());
|
||||
is.mark(1);
|
||||
is.mark(1);
|
||||
assertEquals(2, is.read());
|
||||
assertEquals(3, is.read());
|
||||
is.reset();
|
||||
is.reset();
|
||||
assertEquals(2, is.read());
|
||||
assertEquals(3, is.read());
|
||||
assertThrows(Exception.class, () -> is.mark(-1));
|
||||
} else {
|
||||
assertThrows(Exception.class, () -> is.mark(0));
|
||||
assertThrows(Exception.class, () -> is.mark(10));
|
||||
assertThrows(Exception.class, is::reset);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package it.cavallium.stream;
|
||||
|
||||
import it.cavallium.buffer.Buf;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class TestOutput {
|
||||
|
||||
@Test
|
||||
public void testBufOutputStream() throws IOException {
|
||||
var buf = Buf.createZeroes(Integer.BYTES * 3);
|
||||
var subMiddleBuf = buf.subList(Integer.BYTES, Integer.BYTES * 2);
|
||||
buf.setInt(0, 0);
|
||||
buf.setInt(Integer.BYTES, 5);
|
||||
buf.setInt(Integer.BYTES * 2, 4);
|
||||
var subBuf = buf.subList(Integer.BYTES, Integer.BYTES * 3);
|
||||
var subBufOut = subBuf.binaryOutputStream();
|
||||
var subBufOutData = new SafeDataOutputStream(subBufOut);
|
||||
subBufOutData.writeInt(9);
|
||||
subBufOut.position(0);
|
||||
subBufOutData.writeInt(1);
|
||||
subBufOutData.writeInt(2);
|
||||
var i0 = buf.getInt(0);
|
||||
var i1 = buf.getInt(Integer.BYTES);
|
||||
var i2 = buf.getInt(Integer.BYTES * 2);
|
||||
assertEquals(List.of(0, 1, 2), List.of(i0, i1, i2));
|
||||
{
|
||||
var baos = new ByteArrayOutputStream();
|
||||
var dos = new DataOutputStream(baos);
|
||||
dos.writeInt(1);
|
||||
dos.writeInt(2);
|
||||
assertArrayEquals(baos.toByteArray(), subBufOut.toByteArray());
|
||||
}
|
||||
{
|
||||
var baos = new ByteArrayOutputStream();
|
||||
var dos = new DataOutputStream(baos);
|
||||
dos.writeInt(0);
|
||||
dos.writeInt(1);
|
||||
dos.writeInt(2);
|
||||
assertArrayEquals(baos.toByteArray(), buf.toByteArray());
|
||||
}
|
||||
{
|
||||
var baos = new ByteArrayOutputStream();
|
||||
var dos = new DataOutputStream(baos);
|
||||
dos.writeInt(1);
|
||||
assertArrayEquals(baos.toByteArray(), subMiddleBuf.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideByteArrayOutputStreams")
|
||||
public void testByteArrayOutputStream(SafeByteArrayOutputStream baos) {
|
||||
assertArrayEquals(new byte[0], baos.toByteArray());
|
||||
baos.write(0);
|
||||
baos.write(0);
|
||||
baos.write(0);
|
||||
assertArrayEquals(new byte[3], baos.toByteArray());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideByteArrayOutputStreams")
|
||||
public void testTrim(SafeByteArrayOutputStream baos) {
|
||||
baos.trim();
|
||||
assertEquals(0, baos.array.length);
|
||||
baos.write(10);
|
||||
baos.trim();
|
||||
assertEquals(1, baos.array.length);
|
||||
assertArrayEquals(new byte[] {10}, baos.array);
|
||||
baos.ensureWritable(2);
|
||||
assertEquals(3, baos.array.length);
|
||||
assertArrayEquals(new byte[] {10, 0, 0}, baos.array);
|
||||
}
|
||||
|
||||
public static Stream<SafeByteArrayOutputStream> provideByteArrayOutputStreams() {
|
||||
return Stream.of(new SafeByteArrayOutputStream(),
|
||||
new SafeByteArrayOutputStream(10),
|
||||
new SafeByteArrayOutputStream(8),
|
||||
new SafeByteArrayOutputStream(20),
|
||||
new SafeByteArrayOutputStream()
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user