package com.reandroid.lib.arsc.io; import com.reandroid.lib.arsc.header.HeaderBlock; import java.io.*; public class BlockReader extends InputStream { private final Object mLock=new Object(); private byte[] BUFFER; private final int mStart; private final int mLength; private int mPosition; private boolean mIsClosed; private int mMark; public BlockReader(byte[] buffer, int start, int length) { this.BUFFER=buffer; this.mStart=start; this.mLength=length; this.mPosition =0; } public BlockReader(byte[] buffer) { this(buffer, 0, buffer.length); } public BlockReader(InputStream in) throws IOException { this(loadBuffer(in)); } public BlockReader(File file) throws IOException { this(loadBuffer(file)); } public HeaderBlock readHeaderBlock() throws IOException { int pos=getPosition(); HeaderBlock headerBlock=new HeaderBlock((short)0); try{ headerBlock.readBytes(this); }catch (EOFException ex){ return null; } seek(pos); return headerBlock; } public int searchNextIntPosition(int bytesOffset, int value){ if(mIsClosed || mPosition>=mLength){ return -1; } synchronized (mLock){ int actPos=mStart+mPosition+bytesOffset; int max=available()/4; for(int i=0;i mLength){ len= mLength -start; } start=start+mStart; return new BlockReader(BUFFER, start, len); } public boolean isAvailable(){ if(mIsClosed){ return false; } return available()>0; } public void offset(int off){ int pos=getPosition()+off; seek(pos); } public void seek(int relPos){ if(relPos<0){ relPos=0; }else if(relPos>length()){ relPos=length(); } setPosition(relPos); } private void setPosition(int pos){ if(pos==mPosition){ return; } synchronized (mLock){ mPosition=pos; } } public int length(){ return mLength; } public byte[] readBytes(int len) throws IOException { byte[] result=new byte[len]; if(len==0){ return result; } int len2=read(result); if(len2<0){ throw new EOFException("Finished reading: "+ mPosition); } if(len==len2){ return result; } byte[] result2=new byte[len2]; System.arraycopy(result, 0, result2, 0, len2); return result2; } public int lengthUntilNextZero(int offset, int zeroCount){ if(mIsClosed || mPosition>=mLength){ return 0; } synchronized (mLock){ int actPos=mStart+mPosition-1; int max=available(); int remZero=zeroCount; int len=0; for(int i=0;i=mLength){ return 0; } synchronized (mLock){ int actPos=mStart+mPosition-1; int max=available(); int len=0; boolean zeroFound=false; for(int i=0;i=mLength){ throw new EOFException("Finished reading: "+mPosition); } synchronized (mLock){ int i=0; while (mPosition=mLength){ throw new EOFException("Finished reading: "+mPosition); } int len=bts.length; if(length=mLength){ j++; break; } } return j; } } public int getPosition(){ return mPosition; } public int getActualPosition(){ return mStart + mPosition; } public int getStartPosition(){ return mStart; } @Override public int read() throws IOException { if(mIsClosed){ throw new IOException("Stream is closed"); } int i=mPosition; if(i>=mLength){ throw new EOFException("Finished reading: "+i); } synchronized (mLock){ int actPos=mStart+i; int val=BUFFER[actPos] & 0xff; mPosition++; return val; } } @Override public void mark(int pos){ mMark=pos; } @Override public int available(){ return mLength-mPosition; } @Override public void reset() throws IOException{ if(mIsClosed){ throw new IOException("Can not reset stream is closed"); } mPosition=mMark; } @Override public void close(){ mIsClosed=true; BUFFER=null; mMark=0; } @Override public String toString(){ StringBuilder builder=new StringBuilder(); builder.append(getClass().getSimpleName()); builder.append(": "); if(mIsClosed){ builder.append("Closed"); }else{ int av=available(); if(av==0){ builder.append("Finished: "); builder.append(getPosition()); }else { if(mStart>0){ builder.append("START="); builder.append(mStart); builder.append(", ACTUAL="); builder.append(getActualPosition()); builder.append(", "); } builder.append("POS="); builder.append(getPosition()); builder.append(", available="); builder.append(av); } } return builder.toString(); } private static byte[] loadBuffer(File file) throws IOException { FileInputStream in=new FileInputStream(file); return loadBuffer(in); } private static byte[] loadBuffer(InputStream in) throws IOException { byte[] result=new byte[0]; byte[] buff=new byte[40960]; int len; while((len=in.read(buff))>0){ result=add(result, buff, len); } in.close(); return result; } private static byte[] add(byte[] arr1, byte[] arr2, int len){ byte[] result=new byte[arr1.length + len]; System.arraycopy(arr1, 0, result, 0, arr1.length); System.arraycopy(arr2, 0, result, arr1.length, len); return result; } public static HeaderBlock readHeaderBlock(File file) throws IOException{ InputStream inputStream=new FileInputStream(file); return readHeaderBlock(inputStream); } public static HeaderBlock readHeaderBlock(InputStream inputStream) throws IOException{ byte[] buffer=new byte[8]; inputStream.read(buffer); inputStream.close(); BlockReader reader=new BlockReader(buffer); return reader.readHeaderBlock(); } }