5656 * </pre>
5757 */
5858@ SuppressWarnings ("WeakerAccess" )
59- public class Bytes extends AbstractBytes 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,16 +381,22 @@ public static Bytes random(int length, Random random) {
381381
382382 private final byte [] byteArray ;
383383 private final ByteOrder byteOrder ;
384+ private final BytesFactory factory ;
385+
386+ Bytes (byte [] byteArray , ByteOrder byteOrder ) {
387+ this (byteArray , byteOrder , new Factory ());
388+ }
384389
385390 /**
386391 * Creates a new immutable instance
387392 *
388393 * @param byteArray internal byte array
389394 * @param byteOrder the internal byte order - this is used to interpret given array, not to change it
390395 */
391- public Bytes (byte [] byteArray , ByteOrder byteOrder ) {
396+ Bytes (byte [] byteArray , ByteOrder byteOrder , BytesFactory factory ) {
392397 this .byteArray = byteArray ;
393398 this .byteOrder = byteOrder ;
399+ this .factory = factory ;
394400 }
395401
396402 /* TRANSFORMER **********************************************************************************************/
@@ -580,7 +586,7 @@ public Bytes rightShift(int shiftCount) {
580586 * @return copied instance
581587 */
582588 public Bytes copy () {
583- return new Bytes ( Arrays . copyOf ( internalArray () , length ()), byteOrder , mutable , readonly );
589+ return transform ( new BytesTransformer . CopyTransformer ( 0 , length ()));
584590 }
585591
586592 /**
@@ -591,9 +597,7 @@ public Bytes copy() {
591597 * @return copied instance
592598 */
593599 public Bytes copy (int offset , int length ) {
594- byte [] copy = new byte [length ];
595- System .arraycopy (internalArray (), offset , copy , 0 , copy .length );
596- return new Bytes (copy , byteOrder , mutable , readonly );
600+ return transform (new BytesTransformer .CopyTransformer (offset , length ));
597601 }
598602
599603 /**
@@ -653,22 +657,6 @@ public Bytes shuffle() {
653657 return transform (new BytesTransformer .ShuffleTransformer (new SecureRandom ()));
654658 }
655659
656- /**
657- * Generic transformation of this instance.
658- * <p>
659- * This transformation might be done in-place (ie. without copying the internal array and overwriting its old state),
660- * or on a copy of the internal data, depending on the type (e.g. {@link MutableBytes}) and if the operation can be done
661- * in-place. Therefore the caller has to ensure that certain side-effects, which occur due to the changing of the internal
662- * data, do not create bugs in his/her code. Usually immutability is prefered, but when handling many or big byte arrays,
663- * mutability enables drastically better performance.
664- *
665- * @param transformer used to transform this instance
666- * @return the transformed instance (might be the same, or a new one)
667- */
668- public Bytes transform (BytesTransformer transformer ) {
669- return transformer .transform (this , isMutable ());
670- }
671-
672660 /**
673661 * Copies the specified array, truncating or padding with zeros (if necessary)
674662 * so the copy has the specified length. For all indices that are
@@ -683,28 +671,24 @@ public Bytes transform(BytesTransformer transformer) {
683671 * @return a copy with the desired size or "this" instance if newByteLength == current length
684672 */
685673 public Bytes resize (int newByteLength ) {
686- if (length () == newByteLength ) {
687- return this ;
688- }
689-
690- if (newByteLength < 0 ) {
691- throw new IllegalArgumentException ("cannot resize to smaller than 0" );
692- }
693-
694- if (newByteLength == 0 ) {
695- return new Bytes (new byte [0 ], this );
696- }
697-
698- byte [] resizedArray = new byte [newByteLength ];
699- if (newByteLength > length ()) {
700- System .arraycopy (internalArray (), 0 , resizedArray , Math .max (0 , Math .abs (newByteLength - length ())), Math .min (newByteLength , length ()));
701- } else {
702- System .arraycopy (internalArray (), Math .max (0 , Math .abs (newByteLength - length ())), resizedArray , Math .min (0 , Math .abs (newByteLength - length ())), Math .min (newByteLength , length ()));
703- }
704-
705- return new Bytes (resizedArray , this );
674+ return transform (new BytesTransformer .ResizeTransformer (newByteLength ));
706675 }
707676
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+ }
708692
709693 /* ATTRIBUTES ************************************************************************************************/
710694
@@ -745,6 +729,16 @@ public ByteOrder byteOrder() {
745729 return byteOrder ;
746730 }
747731
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+
748742 /**
749743 * Check if this instance is read only
750744 *
@@ -852,10 +846,9 @@ public double entropy() {
852846 * @return new instance backed by the same data
853847 */
854848 public Bytes duplicate () {
855- return wrap (this );
849+ return factory . wrap (internalArray (), byteOrder );
856850 }
857851
858-
859852 /**
860853 * Set the byte order or endianness of this instance. Default in Java is {@link ByteOrder#BIG_ENDIAN}.
861854 * <p>
@@ -867,7 +860,7 @@ public Bytes duplicate() {
867860 */
868861 public Bytes byteOrder (ByteOrder byteOrder ) {
869862 if (byteOrder != this .byteOrder ) {
870- return new Bytes (internalArray (), byteOrder , mutable , readonly );
863+ return wrap (internalArray (), byteOrder );
871864 }
872865 return this ;
873866 }
@@ -878,11 +871,11 @@ public Bytes byteOrder(ByteOrder byteOrder) {
878871 *
879872 * @return a new instance if not already readonly, or "this" otherwise
880873 */
881- public Bytes readOnly () {
874+ public ReadOnlyBytes readOnly () {
882875 if (isReadOnly ()) {
883- return this ;
876+ return ( ReadOnlyBytes ) this ;
884877 } else {
885- return new Bytes (internalArray (), byteOrder , false , true );
878+ return new ReadOnlyBytes (internalArray (), byteOrder );
886879 }
887880 }
888881
@@ -915,7 +908,7 @@ private ByteBuffer internalBuffer() {
915908 */
916909 public BigInteger bigInteger () {
917910 if (byteOrder == ByteOrder .LITTLE_ENDIAN ) {
918- return new BigInteger (new BytesTransformer .ReverseTransformer ().transform (this , false ). array ( ));
911+ return new BigInteger (new BytesTransformer .ReverseTransformer ().transform (array () , false ));
919912 } else {
920913 return new BigInteger (array ());
921914 }
@@ -942,7 +935,7 @@ public MutableBytes mutable() {
942935 * @return new input stream
943936 */
944937 public InputStream inputStream () {
945- return new ByteArrayInputStream (internalArray ());
938+ return new ByteArrayInputStream (array ());
946939 }
947940
948941 /**
@@ -955,10 +948,7 @@ public InputStream inputStream() {
955948 * @throws ReadOnlyBufferException if this is a read-only instance
956949 */
957950 public byte [] array () {
958- if (!isReadOnly ()) {
959- return internalArray ();
960- }
961- throw new ReadOnlyBufferException ();
951+ return internalArray ();
962952 }
963953
964954 byte [] internalArray () {
@@ -1216,8 +1206,6 @@ public boolean equals(Object o) {
12161206
12171207 Bytes bytes = (Bytes ) o ;
12181208
1219- if (mutable != bytes .mutable ) return false ;
1220- if (readonly != bytes .readonly ) return false ;
12211209 if (!Arrays .equals (byteArray , bytes .byteArray )) return false ;
12221210 return byteOrder != null ? byteOrder .equals (bytes .byteOrder ) : bytes .byteOrder == null ;
12231211 }
@@ -1246,8 +1234,6 @@ public boolean equalsContent(byte[] array) {
12461234 public int hashCode () {
12471235 int result = Arrays .hashCode (byteArray );
12481236 result = 31 * result + (byteOrder != null ? byteOrder .hashCode () : 0 );
1249- result = 31 * result + (mutable ? 1 : 0 );
1250- result = 31 * result + (readonly ? 1 : 0 );
12511237 return result ;
12521238 }
12531239
@@ -1271,4 +1257,11 @@ public String toString() {
12711257 return length () + " bytes " + preview ;
12721258 }
12731259
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+
12741267}
0 commit comments