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}
0 commit comments