/*
 *******************************************************************************
 * Copyright (C) 2004-2011, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.impl;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.VersionInfo;

/**
 * This class reads the *.res resource bundle format
 *
 * (For the latest version of the file format documentation see
 * ICU4C's source/common/uresdata.h file.)
 *
 * File format for .res resource bundle files (formatVersion=2, ICU 4.4)
 *
 * New in formatVersion 2 compared with 1.3: -------------
 *
 * Three new resource types -- String-v2, Table16 and Array16 -- have their
 * values stored in a new array of 16-bit units between the table key strings
 * and the start of the other resources.
 *
 * genrb eliminates duplicates among Unicode string-v2 values.
 * Multiple Unicode strings may use the same offset and string data,
 * or a short string may point to the suffix of a longer string. ("Suffix sharing")
 * For example, one string "abc" may be reused for another string "bc" by pointing
 * to the second character. (Short strings-v2 are NUL-terminated
 * and not preceded by an explicit length value.)
 *
 * It is allowed for all resource types to share values.
 * The swapper code (ures_swap()) has been modified so that it swaps each item
 * exactly once.
 *
 * A resource bundle may use a special pool bundle. Some or all of the table key strings
 * of the using-bundle are omitted, and the key string offsets for such key strings refer
 * to offsets in the pool bundle.
 * The using-bundle's and the pool-bundle's indexes[URES_INDEX_POOL_CHECKSUM] values
 * must match.
 * Two bits in indexes[URES_INDEX_ATTRIBUTES] indicate whether a resource bundle
 * is or uses a pool bundle.
 *
 * Table key strings must be compared in ASCII order, even if they are not
 * stored in ASCII.
 *
 * New in formatVersion 1.3 compared with 1.2: -------------
 *
 * genrb eliminates duplicates among key strings.
 * Multiple table items may share one key string, or one item may point
 * to the suffix of another's key string. ("Suffix sharing")
 * For example, one key "abc" may be reused for another key "bc" by pointing
 * to the second character. (Key strings are NUL-terminated.)
 *
 * -------------
 *
 * An ICU4C resource bundle file (.res) is a binary, memory-mappable file
 * with nested, hierarchical data structures.
 * It physically contains the following:
 *
 *   Resource root; -- 32-bit Resource item, root item for this bundle's tree;
 *                     currently, the root item must be a table or table32 resource item
 *   int32_t indexes[indexes[0]]; -- array of indexes for friendly
 *                                   reading and swapping; see URES_INDEX_* above
 *                                   new in formatVersion 1.1 (ICU 2.8)
 *   char keys[]; -- characters for key strings
 *                   (formatVersion 1.0: up to 65k of characters; 1.1: <2G)
 *                   (minus the space for root and indexes[]),
 *                   which consist of invariant characters (ASCII/EBCDIC) and are NUL-terminated;
 *                   padded to multiple of 4 bytes for 4-alignment of the following data
 *   uint16_t 16BitUnits[]; -- resources that are stored entirely as sequences of 16-bit units
 *                             (new in formatVersion 2/ICU 4.4)
 *                             data is indexed by the offset values in 16-bit resource types,
 *                             with offset 0 pointing to the beginning of this array;
 *                             there is a 0 at offset 0, for empty resources;
 *                             padded to multiple of 4 bytes for 4-alignment of the following data
 *   data; -- data directly and indirectly indexed by the root item;
 *            the structure is determined by walking the tree
 *
 * Each resource bundle item has a 32-bit Resource handle (see typedef above)
 * which contains the item type number in its upper 4 bits (31..28) and either
 * an offset or a direct value in its lower 28 bits (27..0).
 * The order of items is undefined and only determined by walking the tree.
 * Leaves of the tree may be stored first or last or anywhere in between,
 * and it is in theory possible to have unreferenced holes in the file.
 *
 * 16-bit-unit values:
 * Starting with formatVersion 2/ICU 4.4, some resources are stored in a special
 * array of 16-bit units. Each resource value is a sequence of 16-bit units,
 * with no per-resource padding to a 4-byte boundary.
 * 16-bit container types (Table16 and Array16) contain Resource16 values
 * which are offsets to String-v2 resources in the same 16-bit-units array.
 *
 * Direct values:
 * - Empty Unicode strings have an offset value of 0 in the Resource handle itself.
 * - Starting with formatVersion 2/ICU 4.4, an offset value of 0 for
 *   _any_ resource type indicates an empty value.
 * - Integer values are 28-bit values stored in the Resource handle itself;
 *   the interpretation of unsigned vs. signed integers is up to the application.
 *
 * All other types and values use 28-bit offsets to point to the item's data.
 * The offset is an index to the first 32-bit word of the value, relative to the
 * start of the resource data (i.e., the root item handle is at offset 0).
 * To get byte offsets, the offset is multiplied by 4 (or shifted left by 2 bits).
 * All resource item values are 4-aligned.
 *
 * New in formatVersion 2/ICU 4.4: Some types use offsets into the 16-bit-units array,
 * indexing 16-bit units in that array.
 *
 * The structures (memory layouts) for the values for each item type are listed
 * in the table below.
 *
 * Nested, hierarchical structures: -------------
 *
 * Table items contain key-value pairs where the keys are offsets to char * key strings.
 * The values of these pairs are either Resource handles or
 * offsets into the 16-bit-units array, depending on the table type.
 *
 * Array items are simple vectors of Resource handles,
 * or of offsets into the 16-bit-units array, depending on the array type.
 *
 * Table key string offsets: -------
 *
 * Key string offsets are relative to the start of the resource data (of the root handle),
 * i.e., the first string has an offset of 4+sizeof(indexes).
 * (After the 4-byte root handle and after the indexes array.)
 *
 * If the resource bundle uses a pool bundle, then some key strings are stored
 * in the pool bundle rather than in the local bundle itself.
 * - In a Table or Table16, the 16-bit key string offset is local if it is
 *   less than indexes[URES_INDEX_KEYS_TOP]<<2.
 *   Otherwise, subtract indexes[URES_INDEX_KEYS_TOP]<<2 to get the offset into
 *   the pool bundle key strings.
 * - In a Table32, the 32-bit key string offset is local if it is non-negative.
 *   Otherwise, reset bit 31 to get the pool key string offset.
 *
 * Unlike the local offset, the pool key offset is relative to
 * the start of the key strings, not to the start of the bundle.
 *
 * An alias item is special (and new in ICU 2.4): --------------
 *
 * Its memory layout is just like for a UnicodeString, but at runtime it resolves to
 * another resource bundle's item according to the path in the string.
 * This is used to share items across bundles that are in different lookup/fallback
 * chains (e.g., large collation data among zh_TW and zh_HK).
 * This saves space (for large items) and maintenance effort (less duplication of data).
 *
 * --------------------------------------------------------------------------
 *
 * Resource types:
 *
 * Most resources have their values stored at four-byte offsets from the start
 * of the resource data. These values are at least 4-aligned.
 * Some resource values are stored directly in the offset field of the Resource itself.
 * See UResType in unicode/ures.h for enumeration constants for Resource types.
 *
 * Some resources have their values stored as sequences of 16-bit units,
 * at 2-byte offsets from the start of a contiguous 16-bit-unit array between
 * the table key strings and the other resources. (new in formatVersion 2/ICU 4.4)
 * At offset 0 of that array is a 16-bit zero value for empty 16-bit resources.
 * Resource16 values in Table16 and Array16 are 16-bit offsets to String-v2
 * resources, with the offsets relative to the start of the 16-bit-units array.
 *
 * Type Name            Memory layout of values
 *                      (in parentheses: scalar, non-offset values)
 *
 * 0  Unicode String:   int32_t length, UChar[length], (UChar)0, (padding)
 *                  or  (empty string ("") if offset==0)
 * 1  Binary:           int32_t length, uint8_t[length], (padding)
 *                      - the start of the bytes is 16-aligned -
 * 2  Table:            uint16_t count, uint16_t keyStringOffsets[count], (uint16_t padding), Resource[count]
 * 3  Alias:            (physically same value layout as string, new in ICU 2.4)
 * 4  Table32:          int32_t count, int32_t keyStringOffsets[count], Resource[count]
 *                      (new in formatVersion 1.1/ICU 2.8)
 * 5  Table16:          uint16_t count, uint16_t keyStringOffsets[count], Resource16[count]
 *                      (stored in the 16-bit-units array; new in formatVersion 2/ICU 4.4)
 * 6  Unicode String-v2:UChar[length], (UChar)0; length determined by the first UChar:
 *                      - if first is not a trail surrogate, then the length is implicit
 *                        and u_strlen() needs to be called
 *                      - if first<0xdfef then length=first&0x3ff (and skip first)
 *                      - if first<0xdfff then length=((first-0xdfef)<<16) | second UChar
 *                      - if first==0xdfff then length=((second UChar)<<16) | third UChar
 *                      (stored in the 16-bit-units array; new in formatVersion 2/ICU 4.4)
 * 7  Integer:          (28-bit offset is integer value)
 * 8  Array:            int32_t count, Resource[count]
 * 9  Array16:          uint16_t count, Resource16[count]
 *                      (stored in the 16-bit-units array; new in formatVersion 2/ICU 4.4)
 * 14 Integer Vector:   int32_t length, int32_t[length]
 * 15 Reserved:         This value denotes special purpose resources and is for internal use.
 *
 * Note that there are 3 types with data vector values:
 * - Vectors of 8-bit bytes stored as type Binary.
 * - Vectors of 16-bit words stored as type Unicode String or Unicode String-v2
 *                     (no value restrictions, all values 0..ffff allowed!).
 * - Vectors of 32-bit words stored as type Integer Vector.
 */
public final class ICUResourceBundleReader implements ICUBinary.Authenticate {
    /**
     * File format version that this class understands.
     * "ResB"
     */
    private static final byte DATA_FORMAT_ID[] = {(byte)0x52, (byte)0x65, 
                                                     (byte)0x73, (byte)0x42};

    /* indexes[] value names; indexes are generally 32-bit (Resource) indexes */
    private static final int URES_INDEX_LENGTH           = 0;   /* contains URES_INDEX_TOP==the length of indexes[];
                                                                 * formatVersion==1: all bits contain the length of indexes[]
                                                                 *   but the length is much less than 0xff;
                                                                 * formatVersion>1:
                                                                 *   only bits  7..0 contain the length of indexes[],
                                                                 *        bits 31..8 are reserved and set to 0 */
    private static final int URES_INDEX_KEYS_TOP         = 1;   /* contains the top of the key strings, */
                                                                /* same as the bottom of resources or UTF-16 strings, rounded up */
    //ivate static final int URES_INDEX_RESOURCES_TOP    = 2;   /* contains the top of all resources */
    private static final int URES_INDEX_BUNDLE_TOP       = 3;   /* contains the top of the bundle, */
                                                                /* in case it were ever different from [2] */
    //ivate static final int URES_INDEX_MAX_TABLE_LENGTH = 4;   /* max. length of any table */
    private static final int URES_INDEX_ATTRIBUTES       = 5;   /* attributes bit set, see URES_ATT_* (new in formatVersion 1.2) */
    private static final int URES_INDEX_16BIT_TOP        = 6;   /* top of the 16-bit units (UTF-16 string v2 UChars, URES_TABLE16, URES_ARRAY16),
                                                                 * rounded up (new in formatVersion 2.0, ICU 4.4) */
    private static final int URES_INDEX_POOL_CHECKSUM    = 7;   /* checksum of the pool bundle (new in formatVersion 2.0, ICU 4.4) */
    //ivate static final int URES_INDEX_TOP              = 8;

    /*
     * Nofallback attribute, attribute bit 0 in indexes[URES_INDEX_ATTRIBUTES].
     * New in formatVersion 1.2 (ICU 3.6).
     *
     * If set, then this resource bundle is a standalone bundle.
     * If not set, then the bundle participates in locale fallback, eventually
     * all the way to the root bundle.
     * If indexes[] is missing or too short, then the attribute cannot be determined
     * reliably. Dependency checking should ignore such bundles, and loading should
     * use fallbacks.
     */
    private static final int URES_ATT_NO_FALLBACK = 1;

    /*
     * Attributes for bundles that are, or use, a pool bundle.
     * A pool bundle provides key strings that are shared among several other bundles
     * to reduce their total size.
     * New in formatVersion 2 (ICU 4.4).
     */
    private static final int URES_ATT_IS_POOL_BUNDLE = 2;
    private static final int URES_ATT_USES_POOL_BUNDLE = 4;

    private static final boolean DEBUG = false;
    
    private byte[] /* formatVersion, */ dataVersion;

    // See the ResourceData struct in ICU4C/source/common/uresdata.h.
    private String s16BitUnits;
    private byte[] poolBundleKeys;
    private String poolBundleKeysAsString;
    private int rootRes;
    private int localKeyLimit;
    private boolean noFallback; /* see URES_ATT_NO_FALLBACK */
    private boolean isPoolBundle;
    private boolean usesPoolBundle;

    // Fields specific to the Java port.
    private int[] indexes;
    private byte[] keyStrings;
    private String keyStringsAsString;  // null except if isPoolBundle
    private byte[] resourceBytes;
    private int resourceBottom;  // File offset where the mixed-type resources start.

    private static ReaderCache CACHE = new ReaderCache();
    private static final ICUResourceBundleReader NULL_READER = new ICUResourceBundleReader();

    private static class ReaderInfo {
        final String baseName;
        final String localeID;
        final ClassLoader loader;

        ReaderInfo(String baseName, String localeID, ClassLoader loader) {
            this.baseName = (baseName == null) ? "" : baseName;
            this.localeID = (localeID == null) ? "" : localeID;
            this.loader = loader;
        }

        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof ReaderInfo)) {
                return false;
            }
            ReaderInfo info = (ReaderInfo)obj;
            return this.baseName.equals(info.baseName)
                    && this.localeID.equals(info.localeID)
                    && this.loader.equals(info.loader);
        }

        public int hashCode() {
            return baseName.hashCode() ^ localeID.hashCode() ^ loader.hashCode();
        }
    }

    private static class ReaderCache extends SoftCache<ReaderInfo, ICUResourceBundleReader, ReaderInfo> {
        /* (non-Javadoc)
         * @see com.ibm.icu.impl.CacheBase#createInstance(java.lang.Object, java.lang.Object)
         */
        @Override
        protected ICUResourceBundleReader createInstance(ReaderInfo key, ReaderInfo data) {
            String fullName = ICUResourceBundleReader.getFullName(data.baseName, data.localeID);
            InputStream stream = ICUData.getStream(data.loader, fullName);
            if (stream == null) {
                return NULL_READER;
            }
            return new ICUResourceBundleReader(stream, data.baseName, data.localeID, data.loader);
        }
    }

    /*
     * Sole constructor, just used for NULL_READER
     */
    private ICUResourceBundleReader() {
    }

    private ICUResourceBundleReader(InputStream stream, String baseName, String localeID, ClassLoader loader) {
        BufferedInputStream bs = new BufferedInputStream(stream);
        try {
            if (DEBUG)  {
                System.out.println("The InputStream class is: " + stream.getClass().getName());
                System.out.println("The BufferedInputStream class is: " + bs.getClass().getName());
                System.out.println("The bytes avialable in stream before reading the header: " + bs.available());
            }

            dataVersion = ICUBinary.readHeader(bs, DATA_FORMAT_ID, this);

            if (DEBUG) System.out.println("The bytes available in stream after reading the header: " + bs.available());

            readData(bs);
            stream.close();

        } catch (IOException ex) {
            String fullName = ICUResourceBundleReader.getFullName(baseName, localeID);
            throw new RuntimeException("Data file " + fullName + " is corrupt - " + ex.getMessage());
        }

        // set pool bundle keys if necessary
        if (usesPoolBundle) {
            ICUResourceBundleReader poolBundleReader = getReader(baseName, "pool", loader);
            if (!poolBundleReader.isPoolBundle) {
                throw new IllegalStateException("pool.res is not a pool bundle");
            }
            if (poolBundleReader.indexes[URES_INDEX_POOL_CHECKSUM] != indexes[URES_INDEX_POOL_CHECKSUM]) {
                throw new IllegalStateException("pool.res has a different checksum than this bundle");
            }
            poolBundleKeys = poolBundleReader.keyStrings;
            poolBundleKeysAsString = poolBundleReader.keyStringsAsString;
        }
    }

    static ICUResourceBundleReader getReader(String baseName, String localeID, ClassLoader root) {
        ReaderInfo info = new ReaderInfo(baseName, localeID, root);
        ICUResourceBundleReader reader = CACHE.getInstance(info, info);
        if (reader == NULL_READER) {
            return null;
        }
        return reader;
    }

    // See res_init() in ICU4C/source/common/uresdata.c.
    private void readData(InputStream stream) throws IOException {
        DataInputStream ds = new DataInputStream(stream);

        if(DEBUG) System.out.println("The DataInputStream class is: " + ds.getClass().getName());
        if(DEBUG) System.out.println("The available bytes in the stream before reading the data: "+ds.available());

        rootRes = ds.readInt();

        // read the variable-length indexes[] array
        int indexes0 = ds.readInt();
        int indexLength = indexes0 & 0xff;
        indexes = new int[indexLength];
        indexes[URES_INDEX_LENGTH] = indexes0;
        for(int i=1; i<indexLength; i++){
            indexes[i] = ds.readInt();   
        }
        resourceBottom = (1 + indexLength) << 2;

        if(indexLength > URES_INDEX_ATTRIBUTES) {
            // determine if this resource bundle falls back to a parent bundle
            // along normal locale ID fallback
            int att = indexes[URES_INDEX_ATTRIBUTES];
            noFallback = (att & URES_ATT_NO_FALLBACK) != 0;
            isPoolBundle = (att & URES_ATT_IS_POOL_BUNDLE) != 0;
            usesPoolBundle = (att & URES_ATT_USES_POOL_BUNDLE) != 0;
        }

        int length = indexes[URES_INDEX_BUNDLE_TOP]*4;
        if(DEBUG) System.out.println("The number of bytes in the bundle: "+length);

        // Read the local key strings.
        // The keyStrings include NUL characters corresponding to the bytes
        // up to the end of the indexes.
        if(indexes[URES_INDEX_KEYS_TOP] > (1 + indexLength)) {
            int keysBottom = (1 + indexLength) << 2;
            int keysTop = indexes[URES_INDEX_KEYS_TOP] << 2;
            resourceBottom = keysTop;
            if(isPoolBundle) {
                // Shift the key strings down:
                // Pool bundle key strings are used with a 0-based index,
                // unlike regular bundles' key strings for which indexes
                // are based on the start of the bundle data.
                keysTop -= keysBottom;
                keysBottom = 0;
            } else {
                localKeyLimit = keysTop;
            }
            keyStrings = new byte[keysTop];
            ds.readFully(keyStrings, keysBottom, keysTop - keysBottom);
            if(isPoolBundle) {
                // Overwrite trailing padding bytes so that the conversion works.
                while(keysBottom < keysTop && keyStrings[keysTop - 1] == (byte)0xaa) {
                    keyStrings[--keysTop] = 0;
                }
                keyStringsAsString = new String(keyStrings, "US-ASCII");
            }
        }

        // Read the array of 16-bit units.
        // We are not using
        //   new String(keys, "UTF-16BE")
        // because the 16-bit units may not be well-formed Unicode.
        if( indexLength > URES_INDEX_16BIT_TOP &&
            indexes[URES_INDEX_16BIT_TOP] > indexes[URES_INDEX_KEYS_TOP]
        ) {
            int num16BitUnits = (indexes[URES_INDEX_16BIT_TOP] -
                                 indexes[URES_INDEX_KEYS_TOP]) * 2;
            char[] c16BitUnits = new char[num16BitUnits];
            // Note: Calling readFully() to read data into byte[] and copy
            // the data to char[] is faster than calling readChar() one by one
            // for large data
            byte[] c16BitUnitsBytes = new byte[num16BitUnits * 2];
            ds.readFully(c16BitUnitsBytes);
            for (int i = 0; i < num16BitUnits; i++) {
                c16BitUnits[i] = (char)((c16BitUnitsBytes[i*2] << 8) | (c16BitUnitsBytes[i*2 + 1] & 0xFF));
            }
            s16BitUnits = new String(c16BitUnits);
            resourceBottom = indexes[URES_INDEX_16BIT_TOP] << 2;
        } else {
            s16BitUnits = "\0";
        }

        // Read the block of bytes for the mixed-type resources.
        resourceBytes = new byte[length - resourceBottom];
        ds.readFully(resourceBytes);
    }

    VersionInfo getVersion(){
        return VersionInfo.getInstance(dataVersion[0],dataVersion[1],dataVersion[2],dataVersion[3]);   
    }
    public boolean isDataVersionAcceptable(byte version[]){
        // while ICU4C can read formatVersion 1.0 and up,
        // ICU4J requires 1.1 as a minimum
        // formatVersion = version;
        return ((version[0] == 1 && version[1] >= 1) || version[0] == 2);
    }
    
    int getRootResource() {
        return rootRes;
    }
    boolean getNoFallback() {
        return noFallback;
    }
    boolean getUsesPoolBundle() {
        return usesPoolBundle;
    }

    static int RES_GET_TYPE(int res) {
        return res >>> 28;
    }
    private static int RES_GET_OFFSET(int res) {
        return res & 0x0fffffff;
    }
    private int getResourceByteOffset(int offset) {
        return (offset << 2) - resourceBottom;
    }
    /* get signed and unsigned integer values directly from the Resource handle */
    static int RES_GET_INT(int res) {
        return (res << 4) >> 4;
    }
    static int RES_GET_UINT(int res) {
        return res & 0x0fffffff;
    }
    static boolean URES_IS_TABLE(int type) {
        return type==UResourceBundle.TABLE || type==ICUResourceBundle.TABLE16 || type==ICUResourceBundle.TABLE32;
    }

    private static byte[] emptyBytes = new byte[0];
    private static ByteBuffer emptyByteBuffer = ByteBuffer.allocate(0).asReadOnlyBuffer();
    private static char[] emptyChars = new char[0];
    private static int[] emptyInts = new int[0];
    private static String emptyString = "";

    private char getChar(int offset) {
        return (char)((resourceBytes[offset] << 8) | (resourceBytes[offset + 1] & 0xff));
    }
    private char[] getChars(int offset, int count) {
        char[] chars = new char[count];
        for(int i = 0; i < count; offset += 2, ++i) {
            chars[i] = (char)(((int)resourceBytes[offset] << 8) | (resourceBytes[offset + 1] & 0xff));
        }
        return chars;
    }
    private int getInt(int offset) {
        return (resourceBytes[offset] << 24) |
                ((resourceBytes[offset+1] & 0xff) << 16) |
                ((resourceBytes[offset+2] & 0xff) << 8) |
                ((resourceBytes[offset+3] & 0xff));
    }
    private int[] getInts(int offset, int count) {
        int[] ints = new int[count];
        for(int i = 0; i < count; offset += 4, ++i) {
            ints[i] = (resourceBytes[offset] << 24) |
                        ((resourceBytes[offset+1] & 0xff) << 16) |
                        ((resourceBytes[offset+2] & 0xff) << 8) |
                        ((resourceBytes[offset+3] & 0xff));
        }
        return ints;
    }
    private char[] getTable16KeyOffsets(int offset) {
        int length = s16BitUnits.charAt(offset++);
        if(length > 0) {
            return s16BitUnits.substring(offset, offset + length).toCharArray();
        } else {
            return emptyChars;
        }
    }
    private char[] getTableKeyOffsets(int offset) {
        int length = getChar(offset);
        if(length > 0) {
            return getChars(offset + 2, length);
        } else {
            return emptyChars;
        }
    }
    private int[] getTable32KeyOffsets(int offset) {
        int length = getInt(offset);
        if(length > 0) {
            return getInts(offset + 4, length);
        } else {
            return emptyInts;
        }
    }

    /** Refers to ASCII key string bytes, for key string matching. */
    private static final class ByteSequence {
        private byte[] bytes;
        private int offset;
        public ByteSequence(byte[] bytes, int offset) {
            this.bytes = bytes;
            this.offset = offset;
        }
        public byte charAt(int index) {
            return bytes[offset + index];
        }
    }
    private String makeKeyStringFromBytes(int keyOffset) {
        StringBuilder sb = new StringBuilder();
        byte b;
        while((b = keyStrings[keyOffset++]) != 0) {
            sb.append((char)b);
        }
        return sb.toString();
    }
    private String makeKeyStringFromString(int keyOffset) {
        int endOffset = keyOffset;
        while(poolBundleKeysAsString.charAt(endOffset) != 0) {
            ++endOffset;
        }
        return poolBundleKeysAsString.substring(keyOffset, endOffset);
    }
    private ByteSequence RES_GET_KEY16(char keyOffset) {
        if(keyOffset < localKeyLimit) {
            return new ByteSequence(keyStrings, keyOffset);
        } else {
            return new ByteSequence(poolBundleKeys, keyOffset - localKeyLimit);
        }
    }
    private String getKey16String(int keyOffset) {
        if(keyOffset < localKeyLimit) {
            return makeKeyStringFromBytes(keyOffset);
        } else {
            return makeKeyStringFromString(keyOffset - localKeyLimit);
        }
    }
    private ByteSequence RES_GET_KEY32(int keyOffset) {
        if(keyOffset >= 0) {
            return new ByteSequence(keyStrings, keyOffset);
        } else {
            return new ByteSequence(poolBundleKeys, keyOffset & 0x7fffffff);
        }
    }
    private String getKey32String(int keyOffset) {
        if(keyOffset >= 0) {
            return makeKeyStringFromBytes(keyOffset);
        } else {
            return makeKeyStringFromString(keyOffset & 0x7fffffff);
        }
    }
    // Compare the length-specified input key with the
    // NUL-terminated tableKey.
    private static int compareKeys(CharSequence key, ByteSequence tableKey) {
        int i;
        for(i = 0; i < key.length(); ++i) {
            int c2 = tableKey.charAt(i);
            if(c2 == 0) {
                return 1;  // key > tableKey because key is longer.
            }
            int diff = (int)key.charAt(i) - c2;
            if(diff != 0) {
                return diff;
            }
        }
        return -(int)tableKey.charAt(i);
    }
    private int compareKeys(CharSequence key, char keyOffset) {
        return compareKeys(key, RES_GET_KEY16(keyOffset));
    }
    private int compareKeys32(CharSequence key, int keyOffset) {
        return compareKeys(key, RES_GET_KEY32(keyOffset));
    }

    String getString(int res) {
        int offset=RES_GET_OFFSET(res);
        int length;
        if(RES_GET_TYPE(res)==ICUResourceBundle.STRING_V2) {
            int first = s16BitUnits.charAt(offset);
            if((first&0xfffffc00)!=0xdc00) {  // C: if(!U16_IS_TRAIL(first)) {
                if(first==0) {
                    return emptyString;
                }
                int endOffset;
                for(endOffset=offset+1; s16BitUnits.charAt(endOffset)!=0; ++endOffset) {}
                return s16BitUnits.substring(offset, endOffset);
            } else if(first<0xdfef) {
                length=first&0x3ff;
                ++offset;
            } else if(first<0xdfff) {
                length=((first-0xdfef)<<16)|s16BitUnits.charAt(offset+1);
                offset+=2;
            } else {
                length=((int)s16BitUnits.charAt(offset+1)<<16)|s16BitUnits.charAt(offset+2);
                offset+=3;
            }
            return s16BitUnits.substring(offset, offset+length);
        } else if(res==offset) /* RES_GET_TYPE(res)==URES_STRING */ {
            if(res==0) {
                return emptyString;
            } else {
                offset=getResourceByteOffset(offset);
                length=getInt(offset);
                return new String(getChars(offset+4, length));
            }
        } else {
            return null;
        }
    }

    String getAlias(int res) {
        int offset=RES_GET_OFFSET(res);
        int length;
        if(RES_GET_TYPE(res)==ICUResourceBundle.ALIAS) {
            if(offset==0) {
                return emptyString;
            } else {
                offset=getResourceByteOffset(offset);
                length=getInt(offset);
                return new String(getChars(offset+4, length));
            }
        } else {
            return null;
        }
    }

    byte[] getBinary(int res, byte[] ba) {
        int offset=RES_GET_OFFSET(res);
        int length;
        if(RES_GET_TYPE(res)==UResourceBundle.BINARY) {
            if(offset==0) {
                return emptyBytes;
            } else {
                offset=getResourceByteOffset(offset);
                length=getInt(offset);
                if(ba==null || ba.length!=length) {
                    ba=new byte[length];
                }
                System.arraycopy(resourceBytes, offset+4, ba, 0, length);
                return ba;
            }
        } else {
            return null;
        }
    }

    ByteBuffer getBinary(int res) {
        int offset=RES_GET_OFFSET(res);
        int length;
        if(RES_GET_TYPE(res)==UResourceBundle.BINARY) {
            if(offset==0) {
                // Don't just
                //   return emptyByteBuffer;
                // in case it matters whether the buffer's mark is defined or undefined.
                return emptyByteBuffer.duplicate();
            } else {
                offset=getResourceByteOffset(offset);
                length=getInt(offset);
                return ByteBuffer.wrap(resourceBytes, offset+4, length).slice().asReadOnlyBuffer();
            }
        } else {
            return null;
        }
    }

    int[] getIntVector(int res) {
        int offset=RES_GET_OFFSET(res);
        int length;
        if(RES_GET_TYPE(res)==UResourceBundle.INT_VECTOR) {
            if(offset==0) {
                return emptyInts;
            } else {
                offset=getResourceByteOffset(offset);
                length=getInt(offset);
                return getInts(offset+4, length);
            }
        } else {
            return null;
        }
    }

    Container getArray(int res) {
        int type=RES_GET_TYPE(res);
        int offset=RES_GET_OFFSET(res);
        switch(type) {
        case UResourceBundle.ARRAY:
        case ICUResourceBundle.ARRAY16:
            if(offset==0) {
                return new Container(this);
            }
            break;
        default:
            return null;
        }
        switch(type) {
        case UResourceBundle.ARRAY:
            return new Array(this, offset);
        case ICUResourceBundle.ARRAY16:
            return new Array16(this, offset);
        default:
            return null;
        }
    }

    Table getTable(int res) {
        int type=RES_GET_TYPE(res);
        int offset=RES_GET_OFFSET(res);
        switch(type) {
        case UResourceBundle.TABLE:
        case ICUResourceBundle.TABLE16:
        case ICUResourceBundle.TABLE32:
            if(offset==0) {
                return new Table(this);
            }
            break;
        default:
            return null;
        }
        switch(type) {
        case UResourceBundle.TABLE:
            return new Table1632(this, offset);
        case ICUResourceBundle.TABLE16:
            return new Table16(this, offset);
        case ICUResourceBundle.TABLE32:
            return new Table32(this, offset);
        default:
            return null;
        }
    }

    // Container value classes --------------------------------------------- ***

    static class Container {
        protected ICUResourceBundleReader reader;
        protected int size;
        protected int itemsOffset;

        int getSize() {
            return size;
        }
        int getContainerResource(int index) {
            return ICUResourceBundle.RES_BOGUS;
        }
        protected int getContainer16Resource(int index) {
            if (index < 0 || size <= index) {
                return ICUResourceBundle.RES_BOGUS;
            }
            return (ICUResourceBundle.STRING_V2 << 28) |
                   reader.s16BitUnits.charAt(itemsOffset + index);
        }
        protected int getContainer32Resource(int index) {
            if (index < 0 || size <= index) {
                return ICUResourceBundle.RES_BOGUS;
            }
            return reader.getInt(itemsOffset + 4 * index);
        }
        Container(ICUResourceBundleReader reader) {
            this.reader = reader;
        }
    }
    private static final class Array extends Container {
        int getContainerResource(int index) {
            return getContainer32Resource(index);
        }
        Array(ICUResourceBundleReader reader, int offset) {
            super(reader);
            offset = reader.getResourceByteOffset(offset);
            size = reader.getInt(offset);
            itemsOffset = offset + 4;
        }
    }
    private static final class Array16 extends Container {
        int getContainerResource(int index) {
            return getContainer16Resource(index);
        }
        Array16(ICUResourceBundleReader reader, int offset) {
            super(reader);
            size = reader.s16BitUnits.charAt(offset);
            itemsOffset = offset + 1;
        }
    }
    static class Table extends Container {
        protected char[] keyOffsets;
        protected int[] key32Offsets;

        String getKey(int index) {
            if (index < 0 || size <= index) {
                return null;
            }
            return keyOffsets != null ?
                        reader.getKey16String(keyOffsets[index]) :
                        reader.getKey32String(key32Offsets[index]);
        }
        private static final int URESDATA_ITEM_NOT_FOUND = -1;
        int findTableItem(CharSequence key) {
            int mid, start, limit;
            int result;

            /* do a binary search for the key */
            start=0;
            limit=size;
            while(start<limit) {
                mid = (start + limit) >>> 1;
                if (keyOffsets != null) {
                    result = reader.compareKeys(key, keyOffsets[mid]);
                } else {
                    result = reader.compareKeys32(key, key32Offsets[mid]);
                }
                if (result < 0) {
                    limit = mid;
                } else if (result > 0) {
                    start = mid + 1;
                } else {
                    /* We found it! */
                    return mid;
                }
            }
            return URESDATA_ITEM_NOT_FOUND;  /* not found or table is empty. */
        }
        int getTableResource(String resKey) {
            return getContainerResource(findTableItem(resKey));
        }
        Table(ICUResourceBundleReader reader) {
            super(reader);
        }
    }
    private static final class Table1632 extends Table {
        int getContainerResource(int index) {
            return getContainer32Resource(index);
        }
        Table1632(ICUResourceBundleReader reader, int offset) {
            super(reader);
            offset = reader.getResourceByteOffset(offset);
            keyOffsets = reader.getTableKeyOffsets(offset);
            size = keyOffsets.length;
            itemsOffset = offset + 2 * ((size + 2) & ~1);  // Skip padding for 4-alignment.
        }
    }
    private static final class Table16 extends Table {
        int getContainerResource(int index) {
            return getContainer16Resource(index);
        }
        Table16(ICUResourceBundleReader reader, int offset) {
            super(reader);
            keyOffsets = reader.getTable16KeyOffsets(offset);
            size = keyOffsets.length;
            itemsOffset = offset + 1 + size;
        }
    }
    private static final class Table32 extends Table {
        int getContainerResource(int index) {
            return getContainer32Resource(index);
        }
        Table32(ICUResourceBundleReader reader, int offset) {
            super(reader);
            offset = reader.getResourceByteOffset(offset);
            key32Offsets = reader.getTable32KeyOffsets(offset);
            size = key32Offsets.length;
            itemsOffset = offset + 4 * (1 + size);
        }
    }

    private static final String ICU_RESOURCE_SUFFIX = ".res";

    /**
     * Gets the full name of the resource with suffix.
     */
    public static String getFullName(String baseName, String localeName) {
        if (baseName == null || baseName.length() == 0) {
            if (localeName.length() == 0) {
                return localeName = ULocale.getDefault().toString();
            }
            return localeName + ICU_RESOURCE_SUFFIX;
        } else {
            if (baseName.indexOf('.') == -1) {
                if (baseName.charAt(baseName.length() - 1) != '/') {
                    return baseName + "/" + localeName + ICU_RESOURCE_SUFFIX;
                } else {
                    return baseName + localeName + ICU_RESOURCE_SUFFIX;
                }
            } else {
                baseName = baseName.replace('.', '/');
                if (localeName.length() == 0) {
                    return baseName + ICU_RESOURCE_SUFFIX;
                } else {
                    return baseName + "_" + localeName + ICU_RESOURCE_SUFFIX;
                }
            }
        }
    }
}
