/ app / src / main / java / com / reandroid / arsc / item / BlockItem.java
BlockItem.java
  1  /*
  2    *  Copyright (C) 2022 github.com/REAndroid
  3    *
  4    *  Licensed under the Apache License, Version 2.0 (the "License");
  5    *  you may not use this file except in compliance with the License.
  6    *  You may obtain a copy of the License at
  7    *
  8    *      http://www.apache.org/licenses/LICENSE-2.0
  9    *
 10    * Unless required by applicable law or agreed to in writing, software
 11    * distributed under the License is distributed on an "AS IS" BASIS,
 12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13    * See the License for the specific language governing permissions and
 14    * limitations under the License.
 15    */
 16  package com.reandroid.arsc.item;
 17  
 18  import com.reandroid.arsc.base.Block;
 19  import com.reandroid.arsc.base.BlockCounter;
 20  import com.reandroid.arsc.io.BlockReader;
 21  
 22  import java.io.IOException;
 23  import java.io.InputStream;
 24  import java.io.OutputStream;
 25  
 26  public abstract class BlockItem extends Block {
 27  
 28      private byte[] mBytes;
 29  
 30      public BlockItem(int bytesLength){
 31          super();
 32          if(bytesLength == 0){
 33              mBytes = EMPTY;
 34          }else {
 35              mBytes = new byte[bytesLength];
 36          }
 37      }
 38      protected void onBytesChanged(){
 39      }
 40      protected byte[] getBytesInternal() {
 41          return mBytes;
 42      }
 43      void setBytesInternal(byte[] bytes){
 44          setBytesInternal(bytes, true);
 45      }
 46      void setBytesInternal(byte[] bytes, boolean notify){
 47          if(bytes == null || bytes.length == 0){
 48              bytes = EMPTY;
 49          }
 50          if(bytes == mBytes){
 51              return;
 52          }
 53          mBytes = bytes;
 54          if(notify){
 55              onBytesChanged();
 56          }
 57      }
 58      final void setBytesLength(int length){
 59          setBytesLength(length, true);
 60      }
 61      protected final void setBytesLength(int length, boolean notify){
 62          if(length < 0){
 63              length = 0;
 64          }
 65          if(length == 0){
 66              mBytes = EMPTY;
 67              if(notify){
 68                  onBytesChanged();
 69              }
 70              return;
 71          }
 72          int old = mBytes.length;
 73          if(length == old){
 74              return;
 75          }
 76          byte[] bytes = new byte[length];
 77          if(length < old){
 78              old = length;
 79          }
 80          System.arraycopy(mBytes, 0, bytes, 0, old);
 81          mBytes = bytes;
 82          if(notify){
 83              onBytesChanged();
 84          }
 85      }
 86      int getBytesLength(){
 87          return mBytes.length;
 88      }
 89  
 90      @Override
 91      public int countBytes() {
 92          if(isNull()){
 93              return 0;
 94          }
 95          return getBytesInternal().length;
 96      }
 97      @Override
 98      public byte[] getBytes() {
 99          if(isNull()){
100              return null;
101          }
102          return getBytesInternal();
103      }
104      @Override
105      public void onCountUpTo(BlockCounter counter) {
106          if(counter.FOUND){
107              return;
108          }
109          if(counter.END==this){
110              counter.FOUND=true;
111              return;
112          }
113          counter.setCurrent(this);
114          counter.addCount(countBytes());
115      }
116      @Override
117      public void onReadBytes(BlockReader reader) throws IOException{
118          byte[] bytes = getBytesInternal();
119          int length = bytes.length;
120          if(length == 0){
121              return;
122          }
123          reader.readFully(bytes);
124          onBytesChanged();
125      }
126      @Override
127      protected int onWriteBytes(OutputStream stream) throws IOException {
128          byte[] bytes = getBytesInternal();
129          int length = bytes.length;
130          if(length == 0){
131              return 0;
132          }
133          stream.write(bytes, 0, length);
134          return length;
135      }
136  
137      public int readBytes(InputStream inputStream) throws IOException {
138          byte[] bytes=getBytesInternal();
139          if(bytes == null || bytes.length==0){
140              return 0;
141          }
142          int length = bytes.length;
143          int offset = 0;
144          int read = length;
145          while (length > 0 && read > 0){
146              read = inputStream.read(bytes, offset, length);
147              length -= read;
148              offset += read;
149          }
150          onBytesChanged();
151          super.notifyBlockLoad();
152          return offset;
153      }
154      public void setBytes(BlockItem blockItem){
155          if(blockItem != this) {
156              byte[] coming = blockItem.getBytesInternal();
157              setBytesInternal(coming.clone());
158          }
159      }
160  
161      private static final byte[] EMPTY = new byte[0];
162  }