Skip to content

Commit 2a58a69

Browse files
committed
Merge branch 'feat-subtypes'
2 parents e5824b5 + 1a1be60 commit 2a58a69

File tree

9 files changed

+343
-137
lines changed

9 files changed

+343
-137
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2017 Patrick Favre-Bulle
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
package at.favre.lib.bytes;
23+
24+
/**
25+
* Base interface for bytes
26+
*/
27+
public interface AbstractBytes {
28+
29+
/**
30+
* Checks if instance is mutable
31+
*
32+
* @return true if mutable, ie. transformers will change internal array
33+
*/
34+
boolean isMutable();
35+
36+
/**
37+
* Checks if instance is readonly
38+
*
39+
* @return true if readonly, ie. no direct access to the internal array
40+
*/
41+
boolean isReadOnly();
42+
}

src/main/java/at/favre/lib/bytes/Bytes.java

Lines changed: 53 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
* </pre>
5757
*/
5858
@SuppressWarnings("WeakerAccess")
59-
public class Bytes implements Comparable<Bytes> {
59+
public class Bytes implements Comparable<Bytes>, AbstractBytes {
6060

6161
/* FACTORY ***************************************************************************************************/
6262

@@ -93,7 +93,7 @@ public static Bytes allocate(int length, byte defaultValue) {
9393
* @return new instance
9494
*/
9595
public static Bytes wrap(Bytes bytes) {
96-
return new Bytes(bytes.internalArray(), bytes.byteOrder, bytes.mutable, bytes.readonly);
96+
return new Bytes(bytes.internalArray(), bytes.byteOrder);
9797
}
9898

9999
/**
@@ -381,42 +381,22 @@ public static Bytes random(int length, Random random) {
381381

382382
private final byte[] byteArray;
383383
private final ByteOrder byteOrder;
384-
private final boolean mutable;
385-
private final boolean readonly;
384+
private final BytesFactory factory;
386385

387-
/**
388-
* Creates a new immutable instance
389-
*
390-
* @param byteArray internal byte array
391-
* @param byteOrder the internal byte order - this is used to interpret given array, not to change it
392-
*/
393386
Bytes(byte[] byteArray, ByteOrder byteOrder) {
394-
this(byteArray, byteOrder, false, false);
395-
}
396-
397-
/**
398-
* Creates a new instance with given array and copies all attributes from old instance
399-
*
400-
* @param byteArray internal byte array
401-
* @param oldInstance old instance to copy all internal attributes
402-
*/
403-
Bytes(byte[] byteArray, Bytes oldInstance) {
404-
this(byteArray, oldInstance.byteOrder(), oldInstance.mutable, oldInstance.readonly);
387+
this(byteArray, byteOrder, new Factory());
405388
}
406389

407390
/**
408-
* Creates a new instance
391+
* Creates a new immutable instance
409392
*
410393
* @param byteArray internal byte array
411394
* @param byteOrder the internal byte order - this is used to interpret given array, not to change it
412-
* @param mutable if the internal state can be changed
413-
* @param readonly if all getter for internal byte array will fail
414395
*/
415-
Bytes(byte[] byteArray, ByteOrder byteOrder, boolean mutable, boolean readonly) {
396+
Bytes(byte[] byteArray, ByteOrder byteOrder, BytesFactory factory) {
416397
this.byteArray = byteArray;
417398
this.byteOrder = byteOrder;
418-
this.mutable = mutable;
419-
this.readonly = readonly;
399+
this.factory = factory;
420400
}
421401

422402
/* TRANSFORMER **********************************************************************************************/
@@ -606,7 +586,7 @@ public Bytes rightShift(int shiftCount) {
606586
* @return copied instance
607587
*/
608588
public Bytes copy() {
609-
return new Bytes(Arrays.copyOf(internalArray(), length()), byteOrder, mutable, readonly);
589+
return transform(new BytesTransformer.CopyTransformer(0, length()));
610590
}
611591

612592
/**
@@ -617,9 +597,7 @@ public Bytes copy() {
617597
* @return copied instance
618598
*/
619599
public Bytes copy(int offset, int length) {
620-
byte[] copy = new byte[length];
621-
System.arraycopy(internalArray(), offset, copy, 0, copy.length);
622-
return new Bytes(copy, byteOrder, mutable, readonly);
600+
return transform(new BytesTransformer.CopyTransformer(offset, length));
623601
}
624602

625603
/**
@@ -679,22 +657,6 @@ public Bytes shuffle() {
679657
return transform(new BytesTransformer.ShuffleTransformer(new SecureRandom()));
680658
}
681659

682-
/**
683-
* Generic transformation of this instance.
684-
* <p>
685-
* This transformation might be done in-place (ie. without copying the internal array and overwriting its old state),
686-
* or on a copy of the internal data, depending on the type (e.g. {@link MutableBytes}) and if the operation can be done
687-
* in-place. Therefore the caller has to ensure that certain side-effects, which occur due to the changing of the internal
688-
* data, do not create bugs in his/her code. Usually immutability is prefered, but when handling many or big byte arrays,
689-
* mutability enables drastically better performance.
690-
*
691-
* @param transformer used to transform this instance
692-
* @return the transformed instance (might be the same, or a new one)
693-
*/
694-
public Bytes transform(BytesTransformer transformer) {
695-
return transformer.transform(this, mutable);
696-
}
697-
698660
/**
699661
* Copies the specified array, truncating or padding with zeros (if necessary)
700662
* so the copy has the specified length. For all indices that are
@@ -709,28 +671,24 @@ public Bytes transform(BytesTransformer transformer) {
709671
* @return a copy with the desired size or "this" instance if newByteLength == current length
710672
*/
711673
public Bytes resize(int newByteLength) {
712-
if (length() == newByteLength) {
713-
return this;
714-
}
715-
716-
if (newByteLength < 0) {
717-
throw new IllegalArgumentException("cannot resize to smaller than 0");
718-
}
719-
720-
if (newByteLength == 0) {
721-
return new Bytes(new byte[0], this);
722-
}
723-
724-
byte[] resizedArray = new byte[newByteLength];
725-
if (newByteLength > length()) {
726-
System.arraycopy(internalArray(), 0, resizedArray, Math.max(0, Math.abs(newByteLength - length())), Math.min(newByteLength, length()));
727-
} else {
728-
System.arraycopy(internalArray(), Math.max(0, Math.abs(newByteLength - length())), resizedArray, Math.min(0, Math.abs(newByteLength - length())), Math.min(newByteLength, length()));
729-
}
730-
731-
return new Bytes(resizedArray, this);
674+
return transform(new BytesTransformer.ResizeTransformer(newByteLength));
732675
}
733676

677+
/**
678+
* Generic transformation of this instance.
679+
* <p>
680+
* This transformation might be done in-place (ie. without copying the internal array and overwriting its old state),
681+
* or on a copy of the internal data, depending on the type (e.g. {@link MutableBytes}) and if the operation can be done
682+
* in-place. Therefore the caller has to ensure that certain side-effects, which occur due to the changing of the internal
683+
* data, do not create bugs in his/her code. Usually immutability is prefered, but when handling many or big byte arrays,
684+
* mutability enables drastically better performance.
685+
*
686+
* @param transformer used to transform this instance
687+
* @return the transformed instance (might be the same, or a new one)
688+
*/
689+
public Bytes transform(BytesTransformer transformer) {
690+
return factory.wrap(transformer.transform(internalArray(), isMutable()), byteOrder);
691+
}
734692

735693
/* ATTRIBUTES ************************************************************************************************/
736694

@@ -771,13 +729,24 @@ public ByteOrder byteOrder() {
771729
return byteOrder;
772730
}
773731

732+
/**
733+
* Checks if instance is mutable
734+
*
735+
* @return true if mutable, ie. transformers will change internal array
736+
*/
737+
@Override
738+
public boolean isMutable() {
739+
return false;
740+
}
741+
774742
/**
775743
* Check if this instance is read only
776744
*
777745
* @return true if read only
778746
*/
747+
@Override
779748
public boolean isReadOnly() {
780-
return readonly;
749+
return false;
781750
}
782751

783752
/**
@@ -877,10 +846,9 @@ public double entropy() {
877846
* @return new instance backed by the same data
878847
*/
879848
public Bytes duplicate() {
880-
return wrap(this);
849+
return factory.wrap(internalArray(), byteOrder);
881850
}
882851

883-
884852
/**
885853
* Set the byte order or endianness of this instance. Default in Java is {@link ByteOrder#BIG_ENDIAN}.
886854
* <p>
@@ -892,7 +860,7 @@ public Bytes duplicate() {
892860
*/
893861
public Bytes byteOrder(ByteOrder byteOrder) {
894862
if (byteOrder != this.byteOrder) {
895-
return new Bytes(internalArray(), byteOrder, mutable, readonly);
863+
return wrap(internalArray(), byteOrder);
896864
}
897865
return this;
898866
}
@@ -903,11 +871,11 @@ public Bytes byteOrder(ByteOrder byteOrder) {
903871
*
904872
* @return a new instance if not already readonly, or "this" otherwise
905873
*/
906-
public Bytes readOnly() {
907-
if (readonly) {
908-
return this;
874+
public ReadOnlyBytes readOnly() {
875+
if (isReadOnly()) {
876+
return (ReadOnlyBytes) this;
909877
} else {
910-
return new Bytes(internalArray(), byteOrder, false, true);
878+
return new ReadOnlyBytes(internalArray(), byteOrder);
911879
}
912880
}
913881

@@ -940,7 +908,7 @@ private ByteBuffer internalBuffer() {
940908
*/
941909
public BigInteger bigInteger() {
942910
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
943-
return new BigInteger(new BytesTransformer.ReverseTransformer().transform(this, false).array());
911+
return new BigInteger(new BytesTransformer.ReverseTransformer().transform(array(), false));
944912
} else {
945913
return new BigInteger(array());
946914
}
@@ -967,7 +935,7 @@ public MutableBytes mutable() {
967935
* @return new input stream
968936
*/
969937
public InputStream inputStream() {
970-
return new ByteArrayInputStream(internalArray());
938+
return new ByteArrayInputStream(array());
971939
}
972940

973941
/**
@@ -980,10 +948,7 @@ public InputStream inputStream() {
980948
* @throws ReadOnlyBufferException if this is a read-only instance
981949
*/
982950
public byte[] array() {
983-
if (!readonly) {
984-
return internalArray();
985-
}
986-
throw new ReadOnlyBufferException();
951+
return internalArray();
987952
}
988953

989954
byte[] internalArray() {
@@ -1241,8 +1206,6 @@ public boolean equals(Object o) {
12411206

12421207
Bytes bytes = (Bytes) o;
12431208

1244-
if (mutable != bytes.mutable) return false;
1245-
if (readonly != bytes.readonly) return false;
12461209
if (!Arrays.equals(byteArray, bytes.byteArray)) return false;
12471210
return byteOrder != null ? byteOrder.equals(bytes.byteOrder) : bytes.byteOrder == null;
12481211
}
@@ -1271,8 +1234,6 @@ public boolean equalsContent(byte[] array) {
12711234
public int hashCode() {
12721235
int result = Arrays.hashCode(byteArray);
12731236
result = 31 * result + (byteOrder != null ? byteOrder.hashCode() : 0);
1274-
result = 31 * result + (mutable ? 1 : 0);
1275-
result = 31 * result + (readonly ? 1 : 0);
12761237
return result;
12771238
}
12781239

@@ -1296,4 +1257,11 @@ public String toString() {
12961257
return length() + " bytes " + preview;
12971258
}
12981259

1260+
private static class Factory implements BytesFactory {
1261+
@Override
1262+
public Bytes wrap(byte[] array, ByteOrder byteOrder) {
1263+
return new Bytes(array, byteOrder);
1264+
}
1265+
}
1266+
12991267
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2017 Patrick Favre-Bulle
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
package at.favre.lib.bytes;
23+
24+
import java.nio.ByteOrder;
25+
26+
public interface BytesFactory {
27+
Bytes wrap(byte[] array, ByteOrder byteOrder);
28+
}

0 commit comments

Comments
 (0)