package android.content.res;
import java.io.IOException;
import android.content.res.ResourceTypes.ResChunk_header;
import android.content.res.ResourceTypes.ResStringPool_ref;
import android.content.res.ResourceTypes.ResXMLTree_header;
import android.content.res.ResourceTypes.ResXMLTree_node;
import android.util.Errors;
public class ResXMLTree extends ResXMLParser {
int mError = Errors.NO_INIT;
//byte[] mOwnedData = null;
ResXMLTree_header mHeader;
int mSize;
int mDataEnd;
ResStringPool mStrings = new ResStringPool();
int[] mResIds;
int mNumResIds;
ResXMLTree_node mRootNode;
int mRootExt;
int mRootCode;
public ResXMLTree() {
super.init(this);
restart();
}
public ResXMLTree(byte[] data, int offset, int size, boolean copyData) {
super.init(this);
mReader = new IntReader(data, offset, false);
setTo(data, offset, size, copyData);
}
public int setTo(byte[] data, int offset, int size, boolean copyData) {
try {
uninit();
if (mReader == null)
mReader = new IntReader(data, offset, false);
mEventCode = START_DOCUMENT;
mReader.setPosition(offset);
ResChunk_header chunk = new ResChunk_header(mReader.getData(),
mReader.getPosition(), mReader.readInt(2),
mReader.readInt(2), mReader.readInt());
ChunkUtil.checkType(chunk.type, ResourceTypes.RES_XML_TYPE);
mHeader = new ResXMLTree_header(chunk);
mSize = mHeader.header.size;
if (mHeader.header.headerSize > mSize || mSize > size) {
mError = Errors.BAD_TYPE;
restart();
return mError;
}
mDataEnd = mHeader.header.pointer.offset + mSize;
mStrings.uninit();
mRootNode = null;
mResIds = null;
mNumResIds = 0;
// look for string block, res_map block and first xml block
mReader.setPosition(mHeader.header.pointer.offset
+ mHeader.header.headerSize);
chunk = new ResChunk_header(mReader.getData(),
mReader.getPosition(), mReader.readInt(2),
mReader.readInt(2), mReader.readInt());
ResChunk_header lastChunk = chunk;
while (chunk.pointer.offset < (mDataEnd - ResChunk_header.sizeof())
&& (chunk.pointer.offset < (mDataEnd - chunk.size))) {
// TODO validate_chunk
int type = chunk.type;
int chunkSize = chunk.size;
// System.out.println("Chunk start at " + mReader.getPosition()
// + ", type = 0x" + Integer.toHexString(type)
// + ", size = 0x" + Integer.toHexString(chunkSize));
if (type == ResourceTypes.RES_STRING_POOL_TYPE) {
mStrings.setTo(data, chunk.pointer.offset, chunkSize, false);
} else if (type == ResourceTypes.RES_XML_RESOURCE_MAP_TYPE) {
mReader.setPosition(chunk.pointer.offset + chunk.headerSize);
mNumResIds = (chunk.size - chunk.headerSize) / 4;
mResIds = mReader.readIntArray(mNumResIds);
} else if (type >= ResourceTypes.RES_XML_FIRST_CHUNK_TYPE
&& type <= ResourceTypes.RES_XML_LAST_CHUNK_TYPE) {
mCurNode = new ResXMLTree_node(lastChunk, mReader.readInt(),
new ResStringPool_ref(mReader.readInt()));
if (nextNode() == BAD_DOCUMENT) {
mError = Errors.BAD_TYPE;
restart();
return mError;
}
mRootNode = mCurNode;
mRootExt = mCurExt;
mRootCode = mEventCode;
break;
} else {
System.out.println("Skipping unknown chunk!");
}
lastChunk = chunk;
mReader.setPosition(lastChunk.pointer.offset + lastChunk.size);
chunk = new ResChunk_header(mReader.getData(),
mReader.getPosition(), mReader.readInt(2),
mReader.readInt(2), mReader.readInt());
}
if (mRootNode == null) {
System.out.println("");
mError = Errors.BAD_TYPE;
restart();
return mError;
}
mError = mStrings.getError();
} catch (IOException e) {
e.printStackTrace();
}
restart();
return mError;
}
public int getError() {
return mError;
}
public void uninit() {
mStrings.uninit();
mReader = null;
restart();
}
}