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 }