1081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson/* 2081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Copyright (C) 2011 The Android Open Source Project 3081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * 4081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * you may not use this file except in compliance with the License. 6081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * You may obtain a copy of the License at 7081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * 8081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * 10081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Unless required by applicable law or agreed to in writing, software 11081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * See the License for the specific language governing permissions and 14081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * limitations under the License. 15081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson */ 16081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 17081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonpackage com.android.dx.dex; 18081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 19dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilsonimport com.android.dx.io.DexBuffer; 207baa3b69f87348aa2f4f16375a66be59965e8dd4Dan Bornsteinimport com.android.dx.util.DexException; 21081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonimport java.io.IOException; 22dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilsonimport java.io.UnsupportedEncodingException; 23081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonimport java.util.Arrays; 24081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 25081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson/** 26081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * The file header and map. 27081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson */ 28081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonpublic final class TableOfContents { 29081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 30081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson /* 31081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * TODO: factor out ID constants. 32081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson */ 33081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 34081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section header = new Section(0x0000); 35081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section stringIds = new Section(0x0001); 36081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section typeIds = new Section(0x0002); 37081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section protoIds = new Section(0x0003); 38081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section fieldIds = new Section(0x0004); 39081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section methodIds = new Section(0x0005); 40081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section classDefs = new Section(0x0006); 41081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section mapList = new Section(0x1000); 42081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section typeLists = new Section(0x1001); 43081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section annotationSetRefLists = new Section(0x1002); 44081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section annotationSets = new Section(0x1003); 45081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section classDatas = new Section(0x2000); 46081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section codes = new Section(0x2001); 47081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section stringDatas = new Section(0x2002); 48081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section debugInfos = new Section(0x2003); 49081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section annotations = new Section(0x2004); 50081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section encodedArrays = new Section(0x2005); 51081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section annotationsDirectories = new Section(0x2006); 52081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final Section[] sections = { 53081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson header, stringIds, typeIds, protoIds, fieldIds, methodIds, classDefs, mapList, 54081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson typeLists, annotationSetRefLists, annotationSets, classDatas, codes, stringDatas, 55081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson debugInfos, annotations, encodedArrays, annotationsDirectories 56081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson }; 57081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 58081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public int checksum; 59081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public byte[] signature; 60081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public int fileSize; 61081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public int linkSize; 62081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public int linkOff; 63081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public int dataSize; 64081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public int dataOff; 65081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 66081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public TableOfContents() { 67081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson signature = new byte[20]; 68081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 69081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 70dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public void readFrom(DexBuffer buffer) throws IOException { 71dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson readHeader(buffer.open(0)); 72dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson readMap(buffer.open(mapList.off)); 734ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson computeSizesFromOffsets(); 74dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 75dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 76dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson private void readHeader(DexBuffer.Section headerIn) throws UnsupportedEncodingException { 77dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson byte[] magic = headerIn.readByteArray(8); 789fdbd91288a237eb58e18e4de9c729c3c268c318Dan Bornstein int apiTarget = DexFormat.magicToApi(magic); 799fdbd91288a237eb58e18e4de9c729c3c268c318Dan Bornstein 800083c42a76583417303d5795ab60e3653d326c74Jesse Wilson if (apiTarget != DexFormat.API_NO_EXTENDED_OPCODES) { 81081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson throw new DexException("Unexpected magic: " + Arrays.toString(magic)); 82081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 83081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 84dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson checksum = headerIn.readInt(); 85dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson signature = headerIn.readByteArray(20); 86dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson fileSize = headerIn.readInt(); 87dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson int headerSize = headerIn.readInt(); 88081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson if (headerSize != SizeOf.HEADER_ITEM) { 89081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson throw new DexException("Unexpected header: 0x" + Integer.toHexString(headerSize)); 90081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 91dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson int endianTag = headerIn.readInt(); 92081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson if (endianTag != DexFormat.ENDIAN_TAG) { 93081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson throw new DexException("Unexpected endian tag: 0x" + Integer.toHexString(endianTag)); 94081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 95dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson linkSize = headerIn.readInt(); 96dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson linkOff = headerIn.readInt(); 97dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson mapList.off = headerIn.readInt(); 98081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson if (mapList.off == 0) { 99081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson throw new DexException("Cannot merge dex files that do not contain a map"); 100081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 101dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson stringIds.size = headerIn.readInt(); 102dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson stringIds.off = headerIn.readInt(); 103dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson typeIds.size = headerIn.readInt(); 104dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson typeIds.off = headerIn.readInt(); 105dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson protoIds.size = headerIn.readInt(); 106dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson protoIds.off = headerIn.readInt(); 107dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson fieldIds.size = headerIn.readInt(); 108dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson fieldIds.off = headerIn.readInt(); 109dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson methodIds.size = headerIn.readInt(); 110dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson methodIds.off = headerIn.readInt(); 111dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson classDefs.size = headerIn.readInt(); 112dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson classDefs.off = headerIn.readInt(); 113dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson dataSize = headerIn.readInt(); 114dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson dataOff = headerIn.readInt(); 115081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 116081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 117dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson private void readMap(DexBuffer.Section in) throws IOException { 118081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson int mapSize = in.readInt(); 119081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson Section previous = null; 120081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson for (int i = 0; i < mapSize; i++) { 121081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson short type = in.readShort(); 122081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson in.readShort(); // unused 123081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson Section section = getSection(type); 124081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson int size = in.readInt(); 125081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson int offset = in.readInt(); 126081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 127d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson if ((section.size != 0 && section.size != size) 128081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson || (section.off != -1 && section.off != offset)) { 129081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson throw new DexException("Unexpected map value for 0x" + Integer.toHexString(type)); 130081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 131081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 132081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson section.size = size; 133081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson section.off = offset; 134081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 1354ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson if (previous != null && previous.off > section.off) { 1364ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson throw new DexException("Map is unsorted at " + previous + ", " + section); 137081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 138081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 139081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson previous = section; 140081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 1414ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson Arrays.sort(sections); 1424ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson } 143081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 1444ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson public void computeSizesFromOffsets() { 1454ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson int end = dataOff + dataSize; 1464ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson for (int i = sections.length - 1; i >= 0; i--) { 1474ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson Section section = sections[i]; 1484ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson if (section.off == -1) { 1494ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson continue; 1504ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson } 1514ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson if (section.off > end) { 1524ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson throw new DexException("Map is unsorted at " + section); 153081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 1544ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson section.byteCount = end - section.off; 1554ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson end = section.off; 156081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 157081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 158081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 159081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson private Section getSection(short type) { 160081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson for (Section section : sections) { 161081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson if (section.type == type) { 162081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson return section; 163081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 164081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 165081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson throw new IllegalArgumentException("No such map item: " + type); 166081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 167081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 168dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public void writeHeader(DexBuffer.Section out) throws IOException { 1690083c42a76583417303d5795ab60e3653d326c74Jesse Wilson out.write(DexFormat.apiToMagic(DexFormat.API_NO_EXTENDED_OPCODES).getBytes("UTF-8")); 170081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(checksum); 171081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.write(signature); 172081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(fileSize); 173081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(SizeOf.HEADER_ITEM); 174081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(DexFormat.ENDIAN_TAG); 175081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(linkSize); 176081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(linkOff); 177081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(mapList.off); 178081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(stringIds.size); 179081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(stringIds.off); 180081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(typeIds.size); 181081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(typeIds.off); 182081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(protoIds.size); 183081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(protoIds.off); 184081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(fieldIds.size); 185081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(fieldIds.off); 186081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(methodIds.size); 187081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(methodIds.off); 188081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(classDefs.size); 189081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(classDefs.off); 190081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(dataSize); 191081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(dataOff); 192081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 193081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 194dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public void writeMap(DexBuffer.Section out) throws IOException { 195081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson int count = 0; 1964ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson for (Section section : sections) { 197d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson if (section.exists()) { 198081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson count++; 199081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 200081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 201081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 202081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeInt(count); 2034ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson for (Section section : sections) { 204d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson if (section.exists()) { 2054ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson out.writeShort(section.type); 206081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson out.writeShort((short) 0); 2074ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson out.writeInt(section.size); 2084ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson out.writeInt(section.off); 209081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 210081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 211081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 212081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 2134ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson public static class Section implements Comparable<Section> { 214081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final short type; 215d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson public int size = 0; 216081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public int off = -1; 217081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public int byteCount = 0; 218081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 219081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public Section(int type) { 220081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson this.type = (short) type; 221081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 2224ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson 22320d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson public boolean exists() { 224d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson return size > 0; 22520d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson } 22620d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson 2274ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson public int compareTo(Section section) { 2284ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson if (off != section.off) { 2294ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson return off < section.off ? -1 : 1; 2304ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson } 2314ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson return 0; 2324ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson } 2334ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson 2344ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson @Override public String toString() { 2354ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson return String.format("Section[type=%#x,off=%#x,size=%#x]", type, off, size); 2364ceb6bc262c780c456c4d40222a2d0a56eaec02aJesse Wilson } 237081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 238081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson} 239