1/* GENERATED SOURCE. DO NOT MODIFY. */
2/*
3 *******************************************************************************
4 * Copyright (C) 2015, International Business Machines Corporation and
5 * others. All Rights Reserved.
6 *******************************************************************************
7 */
8package android.icu.impl;
9
10import java.nio.ByteBuffer;
11
12import android.icu.util.UResourceBundle;
13import android.icu.util.UResourceTypeMismatchException;
14
15// Class UResource is named consistently with the public class UResourceBundle,
16// in case we want to make it public at some point.
17
18/**
19 * ICU resource bundle key and value types.
20 * @hide Only a subset of ICU is exposed in Android
21 */
22public final class UResource {
23    /**
24     * Represents a resource bundle item's key string.
25     * Avoids object creations as much as possible.
26     * Mutable, not thread-safe.
27     * For permanent storage, use clone() or toString().
28     */
29    public static final class Key implements CharSequence, Cloneable, Comparable<Key> {
30        // Stores a reference to the resource bundle key string bytes array,
31        // with an offset of the key, to avoid creating a String object
32        // until one is really needed.
33        // Alternatively, we could try to always just get the key String object,
34        // and cache it in the reader, and see if that performs better or worse.
35        private byte[] bytes;
36        private int offset;
37        private int length;
38        private String s;
39
40        /**
41         * Constructs an empty resource key string object.
42         */
43        public Key() {}
44
45        private Key(byte[] keyBytes, int keyOffset, int keyLength) {
46            bytes = keyBytes;
47            offset = keyOffset;
48            length = keyLength;
49        }
50
51        /**
52         * Mutates this key for a new NUL-terminated resource key string.
53         * The corresponding ASCII-character bytes are not copied and
54         * must not be changed during the lifetime of this key
55         * (or until the next setBytes() call)
56         * and lifetimes of subSequences created from this key.
57         *
58         * @param keyBytes new key string byte array
59         * @param keyOffset new key string offset
60         */
61        public void setBytes(byte[] keyBytes, int keyOffset) {
62            bytes = keyBytes;
63            offset = keyOffset;
64            for (length = 0; keyBytes[keyOffset + length] != 0; ++length) {}
65            s = null;
66        }
67
68        /**
69         * Mutates this key to an empty resource key string.
70         */
71        public void setToEmpty() {
72            bytes = null;
73            offset = length = 0;
74            s = null;
75        }
76
77        /**
78         * {@inheritDoc}
79         * Does not clone the byte array.
80         */
81        @Override
82        public Key clone() {
83            try {
84                return (Key)super.clone();
85            } catch (CloneNotSupportedException cannotOccur) {
86                return null;
87            }
88        }
89
90        // TODO: Java 6: @Override
91        public char charAt(int i) {
92            assert(0 <= i && i < length);
93            return (char)bytes[offset + i];
94        }
95
96        // TODO: Java 6: @Override
97        public int length() {
98            return length;
99        }
100
101        // TODO: Java 6: @Override
102        public Key subSequence(int start, int end) {
103            assert(0 <= start && start < length);
104            assert(start <= end && end <= length);
105            return new Key(bytes, offset + start, end - start);
106        }
107
108        /**
109         * Creates/caches/returns this resource key string as a Java String.
110         */
111        public String toString() {
112            if (s == null) {
113                s = internalSubString(0, length);
114            }
115            return s;
116        }
117
118        private String internalSubString(int start, int end) {
119            StringBuilder sb = new StringBuilder(end - start);
120            for (int i = start; i < end; ++i) {
121                sb.append((char)bytes[offset + i]);
122            }
123            return sb.toString();
124        }
125
126        /**
127         * Creates a new Java String for a sub-sequence of this resource key string.
128         */
129        public String substring(int start) {
130            assert(0 <= start && start < length);
131            return internalSubString(start, length);
132        }
133
134        /**
135         * Creates a new Java String for a sub-sequence of this resource key string.
136         */
137        public String substring(int start, int end) {
138            assert(0 <= start && start < length);
139            assert(start <= end && end <= length);
140            return internalSubString(start, end);
141        }
142
143        private boolean regionMatches(byte[] otherBytes, int otherOffset, int n) {
144            for (int i = 0; i < n; ++i) {
145                if (bytes[offset + i] != otherBytes[otherOffset + i]) {
146                    return false;
147                }
148            }
149            return true;
150        }
151
152        private boolean regionMatches(int start, CharSequence cs, int n) {
153            for (int i = 0; i < n; ++i) {
154                if (bytes[offset + start + i] != cs.charAt(i)) {
155                    return false;
156                }
157            }
158            return true;
159        }
160
161        @Override
162        public boolean equals(Object other) {
163            if (other == null) {
164                return false;
165            } else if (this == other) {
166                return true;
167            } else if (other instanceof Key) {
168                Key otherKey = (Key)other;
169                return length == otherKey.length &&
170                        regionMatches(otherKey.bytes, otherKey.offset, length);
171            } else {
172                return false;
173            }
174        }
175
176        public boolean contentEquals(CharSequence cs) {
177            if (cs == null) {
178                return false;
179            }
180            return this == cs || (cs.length() == length && regionMatches(0, cs, length));
181        }
182
183        public boolean startsWith(CharSequence cs) {
184            int csLength = cs.length();
185            return csLength <= length && regionMatches(0, cs, csLength);
186        }
187
188        public boolean endsWith(CharSequence cs) {
189            int csLength = cs.length();
190            return csLength <= length && regionMatches(length - csLength, cs, csLength);
191        }
192
193        /**
194         * @return true if the substring of this key starting from the offset
195         *         contains the same characters as the other sequence.
196         */
197        public boolean regionMatches(int start, CharSequence cs) {
198            int csLength = cs.length();
199            return csLength == (length - start) && regionMatches(start, cs, csLength);
200        }
201
202        @Override
203        public int hashCode() {
204            // Never return s.hashCode(), so that
205            // Key.hashCode() is the same whether we have cached s or not.
206            if (length == 0) {
207                return 0;
208            }
209
210            int h = bytes[offset];
211            for (int i = 1; i < length; ++i) {
212                h = 37 * h + bytes[offset];
213            }
214            return h;
215        }
216
217        // TODO: Java 6: @Override
218        public int compareTo(Key other) {
219            return compareTo((CharSequence)other);
220        }
221
222        public int compareTo(CharSequence cs) {
223            int csLength = cs.length();
224            int minLength = length <= csLength ? length : csLength;
225            for (int i = 0; i < minLength; ++i) {
226                int diff = (int)charAt(i) - (int)cs.charAt(i);
227                if (diff != 0) {
228                    return diff;
229                }
230            }
231            return length - csLength;
232        }
233    }
234
235    /**
236     * Represents a resource bundle item's value.
237     * Avoids object creations as much as possible.
238     * Mutable, not thread-safe.
239     */
240    public static abstract class Value {
241        protected Value() {}
242
243        /**
244         * @return ICU resource type like {@link UResourceBundle#getType()},
245         *     for example, {@link UResourceBundle#STRING}
246         */
247        public abstract int getType();
248
249        /**
250         * @see UResourceBundle#getString()
251         * @throws UResourceTypeMismatchException if this is not a string resource
252         */
253        public abstract String getString();
254
255        /**
256         * @throws UResourceTypeMismatchException if this is not an alias resource
257         */
258        public abstract String getAliasString();
259
260        /**
261         * @see UResourceBundle#getInt()
262         * @throws UResourceTypeMismatchException if this is not an integer resource
263         */
264        public abstract int getInt();
265
266        /**
267         * @see UResourceBundle#getUInt()
268         * @throws UResourceTypeMismatchException if this is not an integer resource
269         */
270        public abstract int getUInt();
271
272        /**
273         * @see UResourceBundle#getIntVector()
274         * @throws UResourceTypeMismatchException if this is not an intvector resource
275         */
276        public abstract int[] getIntVector();
277
278        /**
279         * @see UResourceBundle#getBinary()
280         * @throws UResourceTypeMismatchException if this is not a binary-blob resource
281         */
282        public abstract ByteBuffer getBinary();
283
284        /**
285         * Only for debugging.
286         */
287        @Override
288        public String toString() {
289            switch(getType()) {
290            case UResourceBundle.STRING:
291                return getString();
292            case UResourceBundle.INT:
293                return Integer.toString(getInt());
294            case UResourceBundle.INT_VECTOR:
295                int[] iv = getIntVector();
296                StringBuilder sb = new StringBuilder("[");
297                sb.append(iv.length).append("]{");
298                if (iv.length != 0) {
299                    sb.append(iv[0]);
300                    for (int i = 1; i < iv.length; ++i) {
301                        sb.append(", ").append(iv[i]);
302                    }
303                }
304                return sb.append('}').toString();
305            case UResourceBundle.BINARY:
306                return "(binary blob)";
307            case UResourceBundle.ARRAY:  // should not occur
308                return "(array)";
309            case UResourceBundle.TABLE:  // should not occur
310                return "(table)";
311            default:  // should not occur
312                return "???";
313            }
314        }
315    }
316
317    /**
318     * Sink for ICU resource array contents.
319     * The base class does nothing.
320     *
321     * <p>Nested arrays and tables are stored as nested sinks,
322     * never put() as {@link Value} items.
323     */
324    public static class ArraySink {
325        /**
326         * Adds a value from a resource array.
327         *
328         * @param index of the resource array item
329         * @param value resource value
330         */
331        public void put(int index, Value value) {}
332
333        /**
334         * Returns a nested resource array at the array index as another sink.
335         * Creates the sink if none exists for the key.
336         * Returns null if nested arrays are not supported.
337         * The default implementation always returns null.
338         *
339         * @param index of the resource array item
340         * @param size number of array items
341         * @return nested-array sink, or null
342         */
343        public ArraySink getOrCreateArraySink(int index, int size) {
344            return null;
345        }
346
347        /**
348         * Returns a nested resource table at the array index as another sink.
349         * Creates the sink if none exists for the key.
350         * Returns null if nested tables are not supported.
351         * The default implementation always returns null.
352         *
353         * @param index of the resource array item
354         * @param initialSize size hint for creating the sink if necessary
355         * @return nested-table sink, or null
356         */
357        public TableSink getOrCreateTableSink(int index, int initialSize) {
358            return null;
359        }
360
361        /**
362         * "Leaves" the array.
363         * Indicates that all of the resources and sub-resources of the current array
364         * have been enumerated.
365         */
366        public void leave() {}
367    }
368
369    /**
370     * Sink for ICU resource table contents.
371     * The base class does nothing.
372     *
373     * <p>Nested arrays and tables are stored as nested sinks,
374     * never put() as {@link Value} items.
375     */
376    public static class TableSink {
377        /**
378         * Adds a key-value pair from a resource table.
379         *
380         * @param key resource key string
381         * @param value resource value
382         */
383        public void put(Key key, Value value) {}
384
385        /**
386         * Adds a no-fallback/no-inheritance marker for this key.
387         * Used for CLDR no-fallback data values of "∅∅∅"
388         * when enumerating tables with fallback from the specific resource bundle to root.
389         *
390         * <p>The default implementation does nothing.
391         *
392         * @param key to be removed
393         */
394        public void putNoFallback(Key key) {}
395
396        /**
397         * Returns a nested resource array for the key as another sink.
398         * Creates the sink if none exists for the key.
399         * Returns null if nested arrays are not supported.
400         * The default implementation always returns null.
401         *
402         * @param key resource key string
403         * @param size number of array items
404         * @return nested-array sink, or null
405         */
406        public ArraySink getOrCreateArraySink(Key key, int size) {
407            return null;
408        }
409
410        /**
411         * Returns a nested resource table for the key as another sink.
412         * Creates the sink if none exists for the key.
413         * Returns null if nested tables are not supported.
414         * The default implementation always returns null.
415         *
416         * @param key resource key string
417         * @param initialSize size hint for creating the sink if necessary
418         * @return nested-table sink, or null
419         */
420        public TableSink getOrCreateTableSink(Key key, int initialSize) {
421            return null;
422        }
423
424        /**
425         * "Leaves" the table.
426         * Indicates that all of the resources and sub-resources of the current table
427         * have been enumerated.
428         */
429        public void leave() {}
430    }
431}
432