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