1/* GENERATED SOURCE. DO NOT MODIFY. */
2/*
3 ******************************************************************************
4 * Copyright (C) 1996-2015, International Business Machines Corporation and
5 * others. All Rights Reserved.
6 ******************************************************************************
7 */
8
9package android.icu.impl;
10
11import java.io.IOException;
12import java.nio.ByteBuffer;
13import java.util.Arrays;
14
15import android.icu.text.UTF16;
16
17/**
18 * Trie implementation which stores data in int, 32 bits.
19 * 2015-sep-03: Used only in CharsetSelector which could be switched to {@link Trie2_32}
20 * as long as that does not load ICU4C selector data.
21 *
22 * @author synwee
23 * @see android.icu.impl.Trie
24 * @hide Only a subset of ICU is exposed in Android
25 */
26public class IntTrie extends Trie
27{
28    // public constructors ---------------------------------------------
29
30    /**
31    * <p>Creates a new Trie with the settings for the trie data.</p>
32    * <p>Unserialize the 32-bit-aligned input stream and use the data for the
33    * trie.</p>
34    * @param bytes file buffer to a ICU data file, containing the trie
35    * @param dataManipulate object which provides methods to parse the char
36    *                        data
37    * @throws IOException thrown when data reading fails
38    */
39    public IntTrie(ByteBuffer bytes, DataManipulate dataManipulate)
40                                                    throws IOException
41    {
42        super(bytes, dataManipulate);
43        if (!isIntTrie()) {
44            throw new IllegalArgumentException(
45                               "Data given does not belong to a int trie.");
46        }
47    }
48
49    /**
50     * Make a dummy IntTrie.
51     * A dummy trie is an empty runtime trie, used when a real data trie cannot
52     * be loaded.
53     *
54     * The trie always returns the initialValue,
55     * or the leadUnitValue for lead surrogate code points.
56     * The Latin-1 part is always set up to be linear.
57     *
58     * @param initialValue the initial value that is set for all code points
59     * @param leadUnitValue the value for lead surrogate code _units_ that do not
60     *                      have associated supplementary data
61     * @param dataManipulate object which provides methods to parse the char data
62     */
63    @SuppressWarnings("all") // No way to ignore dead code warning specifically - see eclipse bug#282770
64    public IntTrie(int initialValue, int leadUnitValue, DataManipulate dataManipulate) {
65        super(new char[BMP_INDEX_LENGTH+SURROGATE_BLOCK_COUNT], HEADER_OPTIONS_LATIN1_IS_LINEAR_MASK_, dataManipulate);
66
67        int dataLength, latin1Length, i, limit;
68        char block;
69
70        /* calculate the actual size of the dummy trie data */
71
72        /* max(Latin-1, block 0) */
73        dataLength=latin1Length= INDEX_STAGE_1_SHIFT_<=8 ? 256 : DATA_BLOCK_LENGTH;
74        if(leadUnitValue!=initialValue) {
75            dataLength+=DATA_BLOCK_LENGTH;
76        }
77        m_data_=new int[dataLength];
78        m_dataLength_=dataLength;
79
80        m_initialValue_=initialValue;
81
82        /* fill the index and data arrays */
83
84        /* indexes are preset to 0 (block 0) */
85
86        /* Latin-1 data */
87        for(i=0; i<latin1Length; ++i) {
88            m_data_[i]=initialValue;
89        }
90
91        if(leadUnitValue!=initialValue) {
92            /* indexes for lead surrogate code units to the block after Latin-1 */
93            block=(char)(latin1Length>>INDEX_STAGE_2_SHIFT_);
94            i=0xd800>>INDEX_STAGE_1_SHIFT_;
95            limit=0xdc00>>INDEX_STAGE_1_SHIFT_;
96            for(; i<limit; ++i) {
97                m_index_[i]=block;
98            }
99
100            /* data for lead surrogate code units */
101            limit=latin1Length+DATA_BLOCK_LENGTH;
102            for(i=latin1Length; i<limit; ++i) {
103                m_data_[i]=leadUnitValue;
104            }
105        }
106    }
107
108    // public methods --------------------------------------------------
109
110    /**
111    * Gets the value associated with the codepoint.
112    * If no value is associated with the codepoint, a default value will be
113    * returned.
114    * @param ch codepoint
115    * @return offset to data
116    */
117    public final int getCodePointValue(int ch)
118    {
119        int offset;
120
121        // fastpath for U+0000..U+D7FF
122        if(0 <= ch && ch < UTF16.LEAD_SURROGATE_MIN_VALUE) {
123            // copy of getRawOffset()
124            offset = (m_index_[ch >> INDEX_STAGE_1_SHIFT_] << INDEX_STAGE_2_SHIFT_)
125                    + (ch & INDEX_STAGE_3_MASK_);
126            return m_data_[offset];
127        }
128
129        // handle U+D800..U+10FFFF
130        offset = getCodePointOffset(ch);
131        return (offset >= 0) ? m_data_[offset] : m_initialValue_;
132    }
133
134    /**
135    * Gets the value to the data which this lead surrogate character points
136    * to.
137    * Returned data may contain folding offset information for the next
138    * trailing surrogate character.
139    * This method does not guarantee correct results for trail surrogates.
140    * @param ch lead surrogate character
141    * @return data value
142    */
143    public final int getLeadValue(char ch)
144    {
145        return m_data_[getLeadOffset(ch)];
146    }
147
148    /**
149    * Get the value associated with the BMP code point.
150    * Lead surrogate code points are treated as normal code points, with
151    * unfolded values that may differ from getLeadValue() results.
152    * @param ch the input BMP code point
153    * @return trie data value associated with the BMP codepoint
154    */
155    public final int getBMPValue(char ch)
156    {
157        return m_data_[getBMPOffset(ch)];
158    }
159
160    /**
161    * Get the value associated with a pair of surrogates.
162    * @param lead a lead surrogate
163    * @param trail a trail surrogate
164    */
165    public final int getSurrogateValue(char lead, char trail)
166    {
167        if (!UTF16.isLeadSurrogate(lead) || !UTF16.isTrailSurrogate(trail)) {
168            throw new IllegalArgumentException(
169                "Argument characters do not form a supplementary character");
170        }
171        // get fold position for the next trail surrogate
172        int offset = getSurrogateOffset(lead, trail);
173
174        // get the real data from the folded lead/trail units
175        if (offset > 0) {
176            return m_data_[offset];
177        }
178
179        // return m_initialValue_ if there is an error
180        return m_initialValue_;
181    }
182
183    /**
184    * Get a value from a folding offset (from the value of a lead surrogate)
185    * and a trail surrogate.
186    * @param leadvalue the value of a lead surrogate that contains the
187    *        folding offset
188    * @param trail surrogate
189    * @return trie data value associated with the trail character
190    */
191    public final int getTrailValue(int leadvalue, char trail)
192    {
193        if (m_dataManipulate_ == null) {
194            throw new NullPointerException(
195                             "The field DataManipulate in this Trie is null");
196        }
197        int offset = m_dataManipulate_.getFoldingOffset(leadvalue);
198        if (offset > 0) {
199            return m_data_[getRawOffset(offset,
200                                         (char)(trail & SURROGATE_MASK_))];
201        }
202        return m_initialValue_;
203    }
204
205    /**
206     * <p>Gets the latin 1 fast path value.</p>
207     * <p>Note this only works if latin 1 characters have their own linear
208     * array.</p>
209     * @param ch latin 1 characters
210     * @return value associated with latin character
211     */
212    public final int getLatin1LinearValue(char ch)
213    {
214        return m_data_[INDEX_STAGE_3_MASK_ + 1 + ch];
215    }
216
217    /**
218     * Checks if the argument Trie has the same data as this Trie
219     * @param other Trie to check
220     * @return true if the argument Trie has the same data as this Trie, false
221     *         otherwise
222     */
223    ///CLOVER:OFF
224    public boolean equals(Object other)
225    {
226        boolean result = super.equals(other);
227        if (result && other instanceof IntTrie) {
228            IntTrie othertrie = (IntTrie)other;
229            if (m_initialValue_ != othertrie.m_initialValue_
230                || !Arrays.equals(m_data_, othertrie.m_data_)) {
231                return false;
232            }
233            return true;
234        }
235        return false;
236    }
237
238    public int hashCode() {
239        assert false : "hashCode not designed";
240        return 42;
241    }
242    ///CLOVER:ON
243
244    // protected methods -----------------------------------------------
245
246    /**
247    * <p>Parses the input stream and stores its trie content into a index and
248    * data array</p>
249    * @param bytes data buffer containing trie data
250    */
251    protected final void unserialize(ByteBuffer bytes)
252    {
253        super.unserialize(bytes);
254        // one used for initial value
255        m_data_ = ICUBinary.getInts(bytes, m_dataLength_, 0);
256        m_initialValue_ = m_data_[0];
257    }
258
259    /**
260    * Gets the offset to the data which the surrogate pair points to.
261    * @param lead lead surrogate
262    * @param trail trailing surrogate
263    * @return offset to data
264    */
265    protected final int getSurrogateOffset(char lead, char trail)
266    {
267        if (m_dataManipulate_ == null) {
268            throw new NullPointerException(
269                             "The field DataManipulate in this Trie is null");
270        }
271        // get fold position for the next trail surrogate
272        int offset = m_dataManipulate_.getFoldingOffset(getLeadValue(lead));
273
274        // get the real data from the folded lead/trail units
275        if (offset > 0) {
276            return getRawOffset(offset, (char)(trail & SURROGATE_MASK_));
277        }
278
279        // return -1 if there is an error, in this case we return the default
280        // value: m_initialValue_
281        return -1;
282    }
283
284    /**
285    * Gets the value at the argument index.
286    * For use internally in TrieIterator
287    * @param index value at index will be retrieved
288    * @return 32 bit value
289    * @see android.icu.impl.TrieIterator
290    */
291    protected final int getValue(int index)
292    {
293      return m_data_[index];
294    }
295
296    /**
297    * Gets the default initial value
298    * @return 32 bit value
299    */
300    protected final int getInitialValue()
301    {
302        return m_initialValue_;
303    }
304
305    // package private methods -----------------------------------------
306
307    /**
308     * Internal constructor for builder use
309     * @param index the index array to be slotted into this trie
310     * @param data the data array to be slotted into this trie
311     * @param initialvalue the initial value for this trie
312     * @param options trie options to use
313     * @param datamanipulate folding implementation
314     */
315    IntTrie(char index[], int data[], int initialvalue, int options,
316            DataManipulate datamanipulate)
317    {
318        super(index, options, datamanipulate);
319        m_data_ = data;
320        m_dataLength_ = m_data_.length;
321        m_initialValue_ = initialvalue;
322    }
323
324    // private data members --------------------------------------------
325
326    /**
327    * Default value
328    */
329    private int m_initialValue_;
330    /**
331    * Array of char data
332    */
333    private int m_data_[];
334}
335