public static ARSCFile read(IntReader reader) throws IOException { ARSCFile arsc = new ARSCFile(); ReadUtil.readCheckType(reader, ARSC_CHUNK_TYPE); /* size */ reader.readInt(); int groupCount = reader.readInt(); if (groupCount != 1) { throw new IOException("Only one package per file is supported."); } arsc.strings = StringBlock.read(reader); arsc.pkges = new Pkge[1]; arsc.pkges[0] = readPackage(arsc, reader); return arsc; }
private final void doNext() throws IOException { // Delayed initialization. if (m_strings == null) { ChunkUtil.readCheckType(m_reader, CHUNK_AXML_FILE); /* chunkSize */ m_reader.skipInt(); m_strings = StringBlock.read(m_reader); m_namespaces.increaseDepth(); m_operational = true; } if (m_event == END_DOCUMENT) { return; } int event = m_event; resetEventInfo(); while (true) { if (m_decreaseDepth) { m_decreaseDepth = false; m_namespaces.decreaseDepth(); } // Fake END_DOCUMENT event. if (event == END_TAG && m_namespaces.getDepth() == 1 && m_namespaces.getCurrentCount() == 0) { m_event = END_DOCUMENT; break; } int chunkType; if (event == START_DOCUMENT) { // Fake event, see CHUNK_XML_START_TAG handler. chunkType = CHUNK_XML_START_TAG; } else { chunkType = m_reader.readInt(); } if (chunkType == CHUNK_RESOURCEIDS) { int chunkSize = m_reader.readInt(); if (chunkSize < 8 || (chunkSize % 4) != 0) { throw new IOException("Invalid resource ids size (" + chunkSize + ")."); } m_resourceIDs = m_reader.readIntArray(chunkSize / 4 - 2); continue; } if (chunkType < CHUNK_XML_FIRST || chunkType > CHUNK_XML_LAST) { throw new IOException("Invalid chunk type (" + chunkType + ")."); } // Fake START_DOCUMENT event. if (chunkType == CHUNK_XML_START_TAG && event == -1) { m_event = START_DOCUMENT; break; } // Common header. /* chunkSize */ m_reader.skipInt(); int lineNumber = m_reader.readInt(); /* 0xFFFFFFFF */ m_reader.skipInt(); if (chunkType == CHUNK_XML_START_NAMESPACE || chunkType == CHUNK_XML_END_NAMESPACE) { if (chunkType == CHUNK_XML_START_NAMESPACE) { int prefix = m_reader.readInt(); int uri = m_reader.readInt(); m_namespaces.push(prefix, uri); } else { /* prefix */ m_reader.skipInt(); /* uri */ m_reader.skipInt(); m_namespaces.pop(); } continue; } m_lineNumber = lineNumber; if (chunkType == CHUNK_XML_START_TAG) { m_namespaceUri = m_reader.readInt(); m_name = m_reader.readInt(); /* flags? */ m_reader.skipInt(); int attributeCount = m_reader.readInt(); m_idAttribute = (attributeCount >>> 16) - 1; attributeCount &= 0xFFFF; m_classAttribute = m_reader.readInt(); m_styleAttribute = (m_classAttribute >>> 16) - 1; m_classAttribute = (m_classAttribute & 0xFFFF) - 1; m_attributes = m_reader.readIntArray(attributeCount * ATTRIBUTE_LENGHT); for (int i = ATTRIBUTE_IX_VALUE_TYPE; i < m_attributes.length; ) { m_attributes[i] = (m_attributes[i] >>> 24); i += ATTRIBUTE_LENGHT; } m_namespaces.increaseDepth(); m_event = START_TAG; break; } if (chunkType == CHUNK_XML_END_TAG) { m_namespaceUri = m_reader.readInt(); m_name = m_reader.readInt(); m_event = END_TAG; m_decreaseDepth = true; break; } if (chunkType == CHUNK_XML_TEXT) { m_name = m_reader.readInt(); /* ? */ m_reader.skipInt(); /* ? */ m_reader.skipInt(); m_event = TEXT; break; } } }
private static Pkge readPackage(ARSCFile file, IntReader reader) throws IOException { Pkge pkge = new Pkge(); pkge.file = file; ReadUtil.readCheckType(reader, PACKAGE_CHUNK_TYPE); /* size */ reader.skipInt(); pkge.id = reader.readInt(); { final int nameLength = 128; StringBuilder name = new StringBuilder(16); int i = 0; for (; i != nameLength; ) { ++i; int ch = reader.readShort(); if (ch == 0) { break; } name.append((char) ch); } reader.skip((nameLength - i) * 2); reader.skip((nameLength * 2) % 4); pkge.name = name.toString(); } /* signature? */ reader.skipInt(); int assetCount = reader.readInt(); /* idNamesOffset */ reader.skipInt(); /* idNamesCount */ reader.skipInt(); pkge.assetNames = StringBlock.read(reader); pkge.resourceNames = StringBlock.read(reader); pkge.assets = new Asset[assetCount]; ArrayList contents = new ArrayList(); int assetsRead = 0; Asset currentAsset = null; while (reader.available() != 0) { int chunkType = reader.readInt(); if (chunkType != CONTENT_CHUNK_TYPE) { if (currentAsset != null) { currentAsset.contents = new Content[contents.size()]; contents.toArray(currentAsset.contents); contents.clear(); } } if (chunkType == ASSET_CHUNK_TYPE) { currentAsset = readAsset(reader, pkge); pkge.assets[assetsRead] = currentAsset; assetsRead += 1; } else if (chunkType == CONTENT_CHUNK_TYPE) { if (currentAsset == null) { throw new IOException("Invalid chunk sequence: content read before asset."); } contents.add(readContent(reader, currentAsset)); } else { throw new IOException("Unexpected chunk type (" + chunkType + ")."); } } if (currentAsset != null) { currentAsset.contents = new Content[contents.size()]; contents.toArray(currentAsset.contents); contents.clear(); } if (assetsRead != assetCount) { throw new IOException("Not all assets where read (" + (assetCount - assetsRead) + " left)."); } return pkge; }