1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ExceptionWithContext; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * An item in a Dalvik file which is referenced by absolute offset. 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic abstract class OffsettedItem extends Item 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul implements Comparable<OffsettedItem> { 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code > 0;} alignment requirement */ 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int alignment; 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= -1;} the size of this instance when written, in bytes, or 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code -1} if not yet known */ 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int writeSize; 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} section the item was added to, or {@code null} if 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * not yet added 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private Section addedTo; 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code >= -1;} assigned offset of the item from the start of its section, 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * or {@code -1} if not yet assigned 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int offset; 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the absolute offset of the given item, returning {@code 0} 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if handed {@code null}. 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param item {@code null-ok;} the item in question 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the item's absolute offset, or {@code 0} 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if {@code item == null} 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static int getAbsoluteOffsetOr0(OffsettedItem item) { 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (item == null) { 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return 0; 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return item.getAbsoluteOffset(); 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. The offset is initially unassigned. 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param alignment {@code > 0;} output alignment requirement; must be a 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * power of 2 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param writeSize {@code >= -1;} the size of this instance when written, 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in bytes, or {@code -1} if not immediately known 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public OffsettedItem(int alignment, int writeSize) { 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Section.validateAlignment(alignment); 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (writeSize < -1) { 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("writeSize < -1"); 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.alignment = alignment; 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.writeSize = writeSize; 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.addedTo = null; 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.offset = -1; 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@inheritDoc} 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Comparisons for this class are defined to be type-major (if the 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * types don't match then the objects are not equal), with 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #compareTo0} deciding same-type comparisons. 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final boolean equals(Object other) { 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this == other) { 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return true; 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul OffsettedItem otherItem = (OffsettedItem) other; 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ItemType thisType = itemType(); 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ItemType otherType = otherItem.itemType(); 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (thisType != otherType) { 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (compareTo0(otherItem) == 0); 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@inheritDoc} 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Comparisons for this class are defined to be class-major (if the 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * classes don't match then the objects are not equal), with 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #compareTo0} deciding same-class comparisons. 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int compareTo(OffsettedItem other) { 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this == other) { 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return 0; 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ItemType thisType = itemType(); 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ItemType otherType = other.itemType(); 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (thisType != otherType) { 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return thisType.compareTo(otherType); 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return compareTo0(other); 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Sets the write size of this item. This may only be called once 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * per instance, and only if the size was unknown upon instance 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * creation. 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param writeSize {@code > 0;} the write size, in bytes 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final void setWriteSize(int writeSize) { 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (writeSize < 0) { 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("writeSize < 0"); 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this.writeSize >= 0) { 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new UnsupportedOperationException("writeSize already set"); 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.writeSize = writeSize; 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws UnsupportedOperationException thrown if the write size 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is not yet known 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int writeSize() { 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (writeSize < 0) { 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new UnsupportedOperationException("writeSize is unknown"); 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return writeSize; 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final void writeTo(DexFile file, AnnotatedOutput out) { 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.alignTo(alignment); 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (writeSize < 0) { 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new UnsupportedOperationException( 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "writeSize is unknown"); 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.assertCursor(getAbsoluteOffset()); 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (RuntimeException ex) { 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw ExceptionWithContext.withContext(ex, 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "...while writing " + this); 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul writeTo0(file, out); 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the relative item offset. The offset is from the start of 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the section which the instance was written to. 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the offset 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws RuntimeException thrown if the offset is not yet known 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int getRelativeOffset() { 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (offset < 0) { 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("offset not yet known"); 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return offset; 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the absolute item offset. The offset is from the start of 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the file which the instance was written to. 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the offset 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws RuntimeException thrown if the offset is not yet known 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int getAbsoluteOffset() { 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (offset < 0) { 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("offset not yet known"); 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return addedTo.getAbsoluteOffset(offset); 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Indicates that this item has been added to the given section at 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the given offset. It is only valid to call this method once per 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance. 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param addedTo {@code non-null;} the section this instance has 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * been added to 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param offset {@code >= 0;} the desired offset from the start of the 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * section where this instance was placed 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the offset that this instance should be placed at 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in order to meet its alignment constraint 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int place(Section addedTo, int offset) { 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (addedTo == null) { 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("addedTo == null"); 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (offset < 0) { 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("offset < 0"); 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this.addedTo != null) { 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("already written"); 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int mask = alignment - 1; 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul offset = (offset + mask) & ~mask; 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.addedTo = addedTo; 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.offset = offset; 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul place0(addedTo, offset); 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return offset; 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the alignment requirement of this instance. An instance should 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * only be written when so aligned. 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code > 0;} the alignment requirement; must be a power of 2 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int getAlignment() { 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return alignment; 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the absolute offset of this item as a string, suitable for 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * including in annotations. 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the offset string 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final String offsetString() { 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return '[' + Integer.toHexString(getAbsoluteOffset()) + ']'; 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets a short human-readable string representing this instance. 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the human form 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract String toHuman(); 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Compares this instance to another which is guaranteed to be of 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the same class. The default implementation of this method is to 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * throw an exception (unsupported operation). If a particular 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * class needs to actually sort, then it should override this 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * method. 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param other {@code non-null;} instance to compare to 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code -1}, {@code 0}, or {@code 1}, depending 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * on the sort order of this instance and the other 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected int compareTo0(OffsettedItem other) { 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new UnsupportedOperationException("unsupported"); 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Does additional work required when placing an instance. The 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * default implementation of this method is a no-op. If a 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * particular class needs to do something special, then it should 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * override this method. In particular, if this instance did not 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * know its write size up-front, then this method is responsible 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for setting it. 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param addedTo {@code non-null;} the section this instance has been added to 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param offset {@code >= 0;} the offset from the start of the 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * section where this instance was placed 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected void place0(Section addedTo, int offset) { 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This space intentionally left blank. 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Performs the actual write of the contents of this instance to 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the given data section. This is called by {@link #writeTo}, 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * which will have taken care of ensuring alignment. 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param file {@code non-null;} the file to use for reference 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected abstract void writeTo0(DexFile file, AnnotatedOutput out); 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 315