1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2008 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.Hex;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.ArrayList;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Class that represents a map item.
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class MapItem extends OffsettedItem {
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** file alignment of this class, in bytes */
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int ALIGNMENT = 4;
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** write size of this class, in bytes: three {@code uint}s */
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int WRITE_SIZE = (4 * 3);
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} item type this instance covers */
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final ItemType type;
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} section this instance covers */
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final Section section;
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code null-ok;} first item covered or {@code null} if this is
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * a self-reference
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final Item firstItem;
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code null-ok;} last item covered or {@code null} if this is
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * a self-reference
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final Item lastItem;
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code > 0;} count of items covered; {@code 1} if this
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is a self-reference
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final int itemCount;
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs a list item with instances of this class representing
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * the contents of the given array of sections, adding it to the
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * given map section.
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param sections {@code non-null;} the sections
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param mapSection {@code non-null;} the section that the resulting map
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * should be added to; it should be empty on entry to this method
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static void addMap(Section[] sections,
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            MixedItemSection mapSection) {
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (sections == null) {
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("sections == null");
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (mapSection.items().size() != 0) {
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException(
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    "mapSection.items().size() != 0");
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        ArrayList<MapItem> items = new ArrayList<MapItem>(50);
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (Section section : sections) {
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            ItemType currentType = null;
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Item firstItem = null;
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Item lastItem = null;
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int count = 0;
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (Item item : section.items()) {
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                ItemType type = item.itemType();
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                if (type != currentType) {
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    if (count != 0) {
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                        items.add(new MapItem(currentType, section,
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                        firstItem, lastItem, count));
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    }
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    currentType = type;
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    firstItem = item;
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    count = 0;
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                }
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                lastItem = item;
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                count++;
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (count != 0) {
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                // Add a MapItem for the final items in the section.
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                items.add(new MapItem(currentType, section,
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                firstItem, lastItem, count));
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            } else if (section == mapSection) {
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                // Add a MapItem for the self-referential section.
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                items.add(new MapItem(mapSection));
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        mapSection.add(
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                new UniformListItem<MapItem>(ItemType.TYPE_MAP_LIST, items));
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type {@code non-null;} item type this instance covers
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param section {@code non-null;} section this instance covers
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param firstItem {@code non-null;} first item covered
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param lastItem {@code non-null;} last item covered
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param itemCount {@code > 0;} count of items covered
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private MapItem(ItemType type, Section section, Item firstItem,
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Item lastItem, int itemCount) {
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(ALIGNMENT, WRITE_SIZE);
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (type == null) {
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("type == null");
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (section == null) {
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("section == null");
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (firstItem == null) {
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("firstItem == null");
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (lastItem == null) {
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("lastItem == null");
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (itemCount <= 0) {
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("itemCount <= 0");
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.type = type;
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.section = section;
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.firstItem = firstItem;
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.lastItem = lastItem;
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.itemCount = itemCount;
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs a self-referential instance. This instance is meant to
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * represent the section containing the {@code map_list}.
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param section {@code non-null;} section this instance covers
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private MapItem(Section section) {
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(ALIGNMENT, WRITE_SIZE);
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (section == null) {
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("section == null");
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.type = ItemType.TYPE_MAP_LIST;
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.section = section;
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.firstItem = null;
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.lastItem = null;
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.itemCount = 1;
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public ItemType itemType() {
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return ItemType.TYPE_MAP_ITEM;
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toString() {
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringBuffer sb = new StringBuffer(100);
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(getClass().getName());
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append('{');
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(section.toString());
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(' ');
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(type.toHuman());
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append('}');
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sb.toString();
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void addContents(DexFile file) {
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // We have nothing to add.
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final String toHuman() {
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return toString();
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected void writeTo0(DexFile file, AnnotatedOutput out) {
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int value = type.getMapValue();
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int offset;
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (firstItem == null) {
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            offset = section.getFileOffset();
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            offset = section.getAbsoluteItemOffset(firstItem);
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (out.annotates()) {
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(0, offsetString() + ' ' + type.getTypeName() +
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    " map");
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(2, "  type:   " + Hex.u2(value) + " // " +
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    type.toString());
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(2, "  unused: 0");
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  size:   " + Hex.u4(itemCount));
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  offset: " + Hex.u4(offset));
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeShort(value);
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeShort(0); // unused
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(itemCount);
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(offset);
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
236