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 Gurgul
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Collection;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * A section of a {@code .dex} file. Each section consists of a list
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * of items of some sort or other.
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic abstract class Section {
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code null-ok;} name of this part, for annotation purposes */
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final String name;
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} file that this instance is part of */
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final DexFile file;
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code > 0;} alignment requirement for the final output;
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * must be a power of 2 */
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final int alignment;
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code >= -1;} offset from the start of the file to this part, or
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code -1} if not yet known */
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private int fileOffset;
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** whether {@link #prepare} has been called successfully on this
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instance */
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private boolean prepared;
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Validates an alignment.
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param alignment the alignment
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @throws IllegalArgumentException thrown if {@code alignment}
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * isn't a positive power of 2
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static void validateAlignment(int alignment) {
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if ((alignment <= 0) ||
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            (alignment & (alignment - 1)) != 0) {
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("invalid alignment");
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance. The file offset is initially unknown.
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param name {@code null-ok;} the name of this instance, for annotation
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * purposes
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param file {@code non-null;} file that this instance is part of
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param alignment {@code > 0;} alignment requirement for the final output;
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * must be a power of 2
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Section(String name, DexFile file, int alignment) {
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (file == null) {
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("file == null");
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        validateAlignment(alignment);
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.name = name;
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.file = file;
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.alignment = alignment;
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.fileOffset = -1;
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.prepared = false;
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the file that this instance is part of.
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the file
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final DexFile getFile() {
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return file;
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the alignment for this instance's final output.
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code > 0;} the alignment
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final int getAlignment() {
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return alignment;
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the offset from the start of the file to this part. This
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * throws an exception if the offset has not yet been set.
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the file offset
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final int getFileOffset() {
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (fileOffset < 0) {
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException("fileOffset not set");
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return fileOffset;
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Sets the file offset. It is only valid to call this method once
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * once per instance.
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param fileOffset {@code >= 0;} the desired offset from the start of the
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * file where this for this instance
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the offset that this instance should be placed at
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * in order to meet its alignment constraint
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final int setFileOffset(int fileOffset) {
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (fileOffset < 0) {
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("fileOffset < 0");
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (this.fileOffset >= 0) {
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException("fileOffset already set");
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int mask = alignment - 1;
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        fileOffset = (fileOffset + mask) & ~mask;
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.fileOffset = fileOffset;
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return fileOffset;
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Writes this instance to the given raw data object.
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} where to write to
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final void writeTo(AnnotatedOutput out) {
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        throwIfNotPrepared();
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        align(out);
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int cursor = out.getCursor();
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (fileOffset < 0) {
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            fileOffset = cursor;
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (fileOffset != cursor) {
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException("alignment mismatch: for " + this +
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                       ", at " + cursor +
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                       ", but expected " + fileOffset);
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (out.annotates()) {
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (name != null) {
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(0, "\n" + name + ":");
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            } else if (cursor != 0) {
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(0, "\n");
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        writeTo0(out);
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns the absolute file offset, given an offset from the
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * start of this instance's output. This is only valid to call
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * once this instance has been assigned a file offset (via {@link
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * #setFileOffset}).
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param relative {@code >= 0;} the relative offset
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the corresponding absolute file offset
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final int getAbsoluteOffset(int relative) {
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (relative < 0) {
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("relative < 0");
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (fileOffset < 0) {
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException("fileOffset not yet set");
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return fileOffset + relative;
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns the absolute file offset of the given item which must
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * be contained in this section. This is only valid to call
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * once this instance has been assigned a file offset (via {@link
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * #setFileOffset}).
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * <p><b>Note:</b> Subclasses must implement this as appropriate for
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * their contents.</p>
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param item {@code non-null;} the item in question
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the item's absolute file offset
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public abstract int getAbsoluteItemOffset(Item item);
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Prepares this instance for writing. This performs any necessary
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * prerequisites, including particularly adding stuff to other
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * sections. This method may only be called once per instance;
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * subsequent calls will throw an exception.
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final void prepare() {
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        throwIfPrepared();
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        prepare0();
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        prepared = true;
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the collection of all the items in this section.
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * It is not valid to attempt to change the returned list.
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the items
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public abstract Collection<? extends Item> items();
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Does the main work of {@link #prepare}.
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected abstract void prepare0();
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the size of this instance when output, in bytes.
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the size of this instance, in bytes
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public abstract int writeSize();
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Throws an exception if {@link #prepare} has not been
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * called on this instance.
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected final void throwIfNotPrepared() {
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (!prepared) {
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException("not prepared");
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Throws an exception if {@link #prepare} has already been called
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * on this instance.
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected final void throwIfPrepared() {
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (prepared) {
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException("already prepared");
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Aligns the output of the given data to the alignment of this instance.
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} the output to align
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected final void align(AnnotatedOutput out) {
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.alignTo(alignment);
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Writes this instance to the given raw data object. This gets
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * called by {@link #writeTo} after aligning the cursor of
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code out} and verifying that either the assigned file
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * offset matches the actual cursor {@code out} or that the
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * file offset was not previously assigned, in which case it gets
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * assigned to {@code out}'s cursor.
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} where to write to
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected abstract void writeTo0(AnnotatedOutput out);
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns the name of this section, for annotation purposes.
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} name of this part, for annotation purposes
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected final String getName() {
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return name;
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
288