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

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;

import com.ibm.icu.impl.ICUResource.ArraySink;
import com.ibm.icu.impl.ICUResource.TableSink;
import com.ibm.icu.util.ICUException;
import com.ibm.icu.util.ICUUncheckedIOException;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.UResourceTypeMismatchException;
import com.ibm.icu.util.VersionInfo;

/**
 * This class reads the *.res resource bundle format.
 *
 * For the file format documentation see ICU4C's source/common/uresdata.h file.
 */
public final class ICUResourceBundleReader {
    /**
     * File format version that this class understands.
     * "ResB"
     */
    private static final int DATA_FORMAT = 0x52657342;
    private static final class IsAcceptable implements ICUBinary.Authenticate {
        // @Override when we switch to Java 6
        public boolean isDataVersionAcceptable(byte formatVersion[]) {
            return
                    (formatVersion[0] == 1 && (formatVersion[1] & 0xff) >= 1) ||
                    (2 <= formatVersion[0] && formatVersion[0] <= 3);
        }
    }
    private static final IsAcceptable IS_ACCEPTABLE = new IsAcceptable();

    /* indexes[] value names; indexes are generally 32-bit (Resource) indexes */
    /**
     * [0] contains the length of indexes[]
     * which is at most URES_INDEX_TOP of the latest format version
     *
     * 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
     * formatVersion>=3:
     *        bits 31..8 poolStringIndexLimit bits 23..0
     */
    private static final int URES_INDEX_LENGTH           = 0;
    /**
     * [1] contains the top of the key strings,
     *     same as the bottom of resources or UTF-16 strings, rounded up
     */
    private static final int URES_INDEX_KEYS_TOP         = 1;
    /** [2] contains the top of all resources */
    //ivate static final int URES_INDEX_RESOURCES_TOP    = 2;
    /**
     * [3] contains the top of the bundle,
     *     in case it were ever different from [2]
     */
    private static final int URES_INDEX_BUNDLE_TOP       = 3;
    /** [4] max. length of any table */
    private static final int URES_INDEX_MAX_TABLE_LENGTH = 4;
    /**
     * [5] attributes bit set, see URES_ATT_* (new in formatVersion 1.2)
     *
     * formatVersion>=3:
     *   bits 31..16 poolStringIndex16Limit
     *   bits 15..12 poolStringIndexLimit bits 27..24
     */
    private static final int URES_INDEX_ATTRIBUTES       = 5;
    /**
     * [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_16BIT_TOP        = 6;
    /** [7] checksum of the pool bundle (new in formatVersion 2.0, ICU 4.4) */
    private static final int URES_INDEX_POOL_CHECKSUM    = 7;
    //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 CharBuffer EMPTY_16_BIT_UNITS = CharBuffer.wrap("\0");  // read-only

    /**
     * Objects with more value bytes are stored in SoftReferences.
     * Smaller objects (which are not much larger than a SoftReference)
     * are stored directly, avoiding the overhead of the reference.
     */
    static final int LARGE_SIZE = 24;

    private static final boolean DEBUG = false;

    private int /* formatVersion, */ dataVersion;

    // See the ResourceData struct in ICU4C/source/common/uresdata.h.
    /**
     * Buffer of all of the resource bundle bytes after the header.
     * (equivalent of C++ pRoot)
     */
    private ByteBuffer bytes;
    private byte[] keyBytes;
    private CharBuffer b16BitUnits;
    private ICUResourceBundleReader poolBundleReader;
    private int rootRes;
    private int localKeyLimit;
    private int poolStringIndexLimit;
    private int poolStringIndex16Limit;
    private boolean noFallback; /* see URES_ATT_NO_FALLBACK */
    private boolean isPoolBundle;
    private boolean usesPoolBundle;
    private int poolCheckSum;

    private ResourceCache resourceCache;

    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);
            try {
                ByteBuffer inBytes;
                if (data.baseName != null && data.baseName.startsWith(ICUData.ICU_BASE_NAME)) {
                    String itemPath = fullName.substring(ICUData.ICU_BASE_NAME.length() + 1);
                    inBytes = ICUBinary.getData(data.loader, fullName, itemPath);
                    if (inBytes == null) {
                        return NULL_READER;
                    }
                } else {
                    @SuppressWarnings("resource")  // Closed by getByteBufferFromInputStreamAndCloseStream().
                    InputStream stream = ICUData.getStream(data.loader, fullName);
                    if (stream == null) {
                        return NULL_READER;
                    }
                    inBytes = ICUBinary.getByteBufferFromInputStreamAndCloseStream(stream);
                }
                return new ICUResourceBundleReader(inBytes, data.baseName, data.localeID, data.loader);
            } catch (IOException ex) {
                throw new ICUUncheckedIOException("Data file " + fullName + " is corrupt - " + ex.getMessage(), ex);
            }
        }
    }

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

    private ICUResourceBundleReader(ByteBuffer inBytes,
            String baseName, String localeID,
            ClassLoader loader) throws IOException {
        init(inBytes);

        // set pool bundle if necessary
        if (usesPoolBundle) {
            poolBundleReader = getReader(baseName, "pool", loader);
            if (!poolBundleReader.isPoolBundle) {
                throw new IllegalStateException("pool.res is not a pool bundle");
            }
            if (poolBundleReader.poolCheckSum != poolCheckSum) {
                throw new IllegalStateException("pool.res has a different checksum than this bundle");
            }
        }
    }

    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 init(ByteBuffer inBytes) throws IOException {
        dataVersion = ICUBinary.readHeader(inBytes, DATA_FORMAT, IS_ACCEPTABLE);
        int majorFormatVersion = inBytes.get(16);
        bytes = ICUBinary.sliceWithOrder(inBytes);
        int dataLength = bytes.remaining();

        if(DEBUG) System.out.println("The ByteBuffer is direct (memory-mapped): " + bytes.isDirect());
        if(DEBUG) System.out.println("The available bytes in the buffer before reading the data: " + dataLength);

        rootRes = bytes.getInt(0);

        // Bundles with formatVersion 1.1 and later contain an indexes[] array.
        // We need it so that we can read the key string bytes up front, for lookup performance.

        // read the variable-length indexes[] array
        int indexes0 = getIndexesInt(URES_INDEX_LENGTH);
        int indexLength = indexes0 & 0xff;
        if(indexLength <= URES_INDEX_MAX_TABLE_LENGTH) {
            throw new ICUException("not enough indexes");
        }
        int bundleTop;
        if(dataLength < ((1 + indexLength) << 2) ||
                dataLength < ((bundleTop = getIndexesInt(URES_INDEX_BUNDLE_TOP)) << 2)) {
            throw new ICUException("not enough bytes");
        }
        int maxOffset = bundleTop - 1;

        if (majorFormatVersion >= 3) {
            // In formatVersion 1, the indexLength took up this whole int.
            // In version 2, bits 31..8 were reserved and always 0.
            // In version 3, they contain bits 23..0 of the poolStringIndexLimit.
            // Bits 27..24 are in indexes[URES_INDEX_ATTRIBUTES] bits 15..12.
            poolStringIndexLimit = indexes0 >>> 8;
        }
        if(indexLength > URES_INDEX_ATTRIBUTES) {
            // determine if this resource bundle falls back to a parent bundle
            // along normal locale ID fallback
            int att = getIndexesInt(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;
            poolStringIndexLimit |= (att & 0xf000) << 12;  // bits 15..12 -> 27..24
            poolStringIndex16Limit = att >>> 16;
        }

        int keysBottom = 1 + indexLength;
        int keysTop = getIndexesInt(URES_INDEX_KEYS_TOP);
        if(keysTop > keysBottom) {
            // Deserialize the key strings up front.
            // Faster table item search at the cost of slower startup and some heap memory.
            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.
                keyBytes = new byte[(keysTop - keysBottom) << 2];
                bytes.position(keysBottom << 2);
            } else {
                localKeyLimit = keysTop << 2;
                keyBytes = new byte[localKeyLimit];
            }
            bytes.get(keyBytes);
        }

        // Read the array of 16-bit units.
        if(indexLength > URES_INDEX_16BIT_TOP) {
            int _16BitTop = getIndexesInt(URES_INDEX_16BIT_TOP);
            if(_16BitTop > keysTop) {
                int num16BitUnits = (_16BitTop - keysTop) * 2;
                bytes.position(keysTop << 2);
                b16BitUnits = bytes.asCharBuffer();
                b16BitUnits.limit(num16BitUnits);
                maxOffset |= num16BitUnits - 1;
            } else {
                b16BitUnits = EMPTY_16_BIT_UNITS;
            }
        } else {
            b16BitUnits = EMPTY_16_BIT_UNITS;
        }

        if(indexLength > URES_INDEX_POOL_CHECKSUM) {
            poolCheckSum = getIndexesInt(URES_INDEX_POOL_CHECKSUM);
        }

        if(!isPoolBundle || b16BitUnits.length() > 1) {
            resourceCache = new ResourceCache(maxOffset);
        }

        // Reset the position for future .asCharBuffer() etc.
        bytes.position(0);
    }

    private int getIndexesInt(int i) {
        return bytes.getInt((1 + i) << 2);
    }

    VersionInfo getVersion() {
        return ICUBinary.getVersionInfoFromCompactInt(dataVersion);
    }

    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;
    }
    /* 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_ARRAY(int type) {
        return type == UResourceBundle.ARRAY || type == ICUResourceBundle.ARRAY16;
    }
    static boolean URES_IS_TABLE(int type) {
        return type==UResourceBundle.TABLE || type==ICUResourceBundle.TABLE16 || type==ICUResourceBundle.TABLE32;
    }

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

    private char[] getChars(int offset, int count) {
        char[] chars = new char[count];
        if (count <= 16) {
            for(int i = 0; i < count; offset += 2, ++i) {
                chars[i] = bytes.getChar(offset);
            }
        } else {
            CharBuffer temp = bytes.asCharBuffer();
            temp.position(offset / 2);
            temp.get(chars);
        }
        return chars;
    }
    private int getInt(int offset) {
        return bytes.getInt(offset);
    }
    private int[] getInts(int offset, int count) {
        int[] ints = new int[count];
        if (count <= 16) {
            for(int i = 0; i < count; offset += 4, ++i) {
                ints[i] = bytes.getInt(offset);
            }
        } else {
            IntBuffer temp = bytes.asIntBuffer();
            temp.position(offset / 4);
            temp.get(ints);
        }
        return ints;
    }
    private char[] getTable16KeyOffsets(int offset) {
        int length = b16BitUnits.charAt(offset++);
        if(length > 0) {
            char[] result = new char[length];
            if(length <= 16) {
                for(int i = 0; i < length; ++i) {
                    result[i] = b16BitUnits.charAt(offset++);
                }
            } else {
                CharBuffer temp = b16BitUnits.duplicate();
                temp.position(offset);
                temp.get(result);
            }
            return result;
        } else {
            return emptyChars;
        }
    }
    private char[] getTableKeyOffsets(int offset) {
        int length = bytes.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;
        }
    }

    private static String makeKeyStringFromBytes(byte[] keyBytes, int keyOffset) {
        StringBuilder sb = new StringBuilder();
        byte b;
        while((b = keyBytes[keyOffset]) != 0) {
            ++keyOffset;
            sb.append((char)b);
        }
        return sb.toString();
    }
    private String getKey16String(int keyOffset) {
        if(keyOffset < localKeyLimit) {
            return makeKeyStringFromBytes(keyBytes, keyOffset);
        } else {
            return makeKeyStringFromBytes(poolBundleReader.keyBytes, keyOffset - localKeyLimit);
        }
    }
    private String getKey32String(int keyOffset) {
        if(keyOffset >= 0) {
            return makeKeyStringFromBytes(keyBytes, keyOffset);
        } else {
            return makeKeyStringFromBytes(poolBundleReader.keyBytes, keyOffset & 0x7fffffff);
        }
    }
    private void setKeyFromKey16(int keyOffset, ICUResource.Key key) {
        if(keyOffset < localKeyLimit) {
            key.setBytes(keyBytes, keyOffset);
        } else {
            key.setBytes(poolBundleReader.keyBytes, keyOffset - localKeyLimit);
        }
    }
    private void setKeyFromKey32(int keyOffset, ICUResource.Key key) {
        if(keyOffset >= 0) {
            key.setBytes(keyBytes, keyOffset);
        } else {
            key.setBytes(poolBundleReader.keyBytes, keyOffset & 0x7fffffff);
        }
    }
    private int compareKeys(CharSequence key, char keyOffset) {
        if(keyOffset < localKeyLimit) {
            return ICUBinary.compareKeys(key, keyBytes, keyOffset);
        } else {
            return ICUBinary.compareKeys(key, poolBundleReader.keyBytes, keyOffset - localKeyLimit);
        }
    }
    private int compareKeys32(CharSequence key, int keyOffset) {
        if(keyOffset >= 0) {
            return ICUBinary.compareKeys(key, keyBytes, keyOffset);
        } else {
            return ICUBinary.compareKeys(key, poolBundleReader.keyBytes, keyOffset & 0x7fffffff);
        }
    }

    /**
     * @return a string from the local bundle's b16BitUnits at the local offset
     */
    String getStringV2(int res) {
        // Use the pool bundle's resource cache for pool bundle strings;
        // use the local bundle's cache for local strings.
        // The cache requires a resource word with the proper type,
        // and with an offset that is local to this bundle so that the offset fits
        // within the maximum number of bits for which the cache was constructed.
        assert RES_GET_TYPE(res) == ICUResourceBundle.STRING_V2;
        int offset = RES_GET_OFFSET(res);
        assert offset != 0;  // handled by the caller
        Object value = resourceCache.get(res);
        if(value != null) {
            return (String)value;
        }
        String s;
        int first = b16BitUnits.charAt(offset);
        if((first&0xfffffc00)!=0xdc00) {  // C: if(!U16_IS_TRAIL(first)) {
            if(first==0) {
                return emptyString;  // Should not occur, but is not forbidden.
            }
            StringBuilder sb = new StringBuilder();
            sb.append((char)first);
            char c;
            while((c = b16BitUnits.charAt(++offset)) != 0) {
                sb.append(c);
            }
            s = sb.toString();
        } else {
            int length;
            if(first<0xdfef) {
                length=first&0x3ff;
                ++offset;
            } else if(first<0xdfff) {
                length=((first-0xdfef)<<16)|b16BitUnits.charAt(offset+1);
                offset+=2;
            } else {
                length=((int)b16BitUnits.charAt(offset+1)<<16)|b16BitUnits.charAt(offset+2);
                offset+=3;
            }
            // Cast up to CharSequence to insulate against the CharBuffer.subSequence() return type change
            // which makes code compiled for a newer JDK (7 and up) not run on an older one (6 and below).
            s = ((CharSequence) b16BitUnits).subSequence(offset, offset + length).toString();
        }
        return (String)resourceCache.putIfAbsent(res, s, s.length() * 2);
    }

    private String makeStringFromBytes(int offset, int length) {
        if (length <= 16) {
            StringBuilder sb = new StringBuilder(length);
            for (int i = 0; i < length; offset += 2, ++i) {
                sb.append(bytes.getChar(offset));
            }
            return sb.toString();
        } else {
            CharSequence cs = bytes.asCharBuffer();
            offset /= 2;
            return cs.subSequence(offset, offset + length).toString();
        }
    }

    String getString(int res) {
        int offset=RES_GET_OFFSET(res);
        if(res != offset /* RES_GET_TYPE(res) != URES_STRING */ &&
                RES_GET_TYPE(res) != ICUResourceBundle.STRING_V2) {
            return null;
        }
        if(offset == 0) {
            return emptyString;
        }
        if (res != offset) {  // STRING_V2
            if (offset < poolStringIndexLimit) {
                return poolBundleReader.getStringV2(res);
            } else {
                return getStringV2(res - poolStringIndexLimit);
            }
        }
        Object value = resourceCache.get(res);
        if(value != null) {
            return (String)value;
        }
        offset=getResourceByteOffset(offset);
        int length = getInt(offset);
        String s = makeStringFromBytes(offset+4, length);
        return (String)resourceCache.putIfAbsent(res, s, s.length() * 2);
    }

    /**
     * CLDR string value "∅∅∅"=="\u2205\u2205\u2205" prevents fallback to the parent bundle.
     */
    private boolean isNoInheritanceMarker(int res) {
        int offset = RES_GET_OFFSET(res);
        if (offset == 0) {
            // empty string
        } else if (res == offset) {
            offset = getResourceByteOffset(offset);
            return getInt(offset) == 3 && bytes.getChar(offset + 4) == 0x2205 &&
                    bytes.getChar(offset + 6) == 0x2205 && bytes.getChar(offset + 8) == 0x2205;
        } else if (RES_GET_TYPE(res) == ICUResourceBundle.STRING_V2) {
            if (offset < poolStringIndexLimit) {
                return poolBundleReader.isStringV2NoInheritanceMarker(offset);
            } else {
                return isStringV2NoInheritanceMarker(offset - poolStringIndexLimit);
            }
        }
        return false;
    }

    private boolean isStringV2NoInheritanceMarker(int offset) {
        int first = b16BitUnits.charAt(offset);
        if (first == 0x2205) {  // implicit length
            return b16BitUnits.charAt(offset + 1) == 0x2205 &&
                    b16BitUnits.charAt(offset + 2) == 0x2205 &&
                    b16BitUnits.charAt(offset + 3) == 0;
        } else if (first == 0xdc03) {  // explicit length 3 (should not occur)
            return b16BitUnits.charAt(offset + 1) == 0x2205 &&
                    b16BitUnits.charAt(offset + 2) == 0x2205 &&
                    b16BitUnits.charAt(offset + 3) == 0x2205;
        } else {
            // Assume that the string has not been stored with more length units than necessary.
            return false;
        }
    }

    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 {
                Object value = resourceCache.get(res);
                if(value != null) {
                    return (String)value;
                }
                offset=getResourceByteOffset(offset);
                length=getInt(offset);
                String s = makeStringFromBytes(offset + 4, length);
                return (String)resourceCache.putIfAbsent(res, s, length * 2);
            }
        } 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(length==0) {
                    return emptyBytes;
                }
                // Not cached: The array would have to be cloned anyway because
                // the cache must not be writable via the returned reference.
                if(ba==null || ba.length!=length) {
                    ba=new byte[length];
                }
                offset += 4;
                if(length <= 16) {
                    for(int i = 0; i < length; ++i) {
                        ba[i] = bytes.get(offset++);
                    }
                } else {
                    ByteBuffer temp = bytes.duplicate();
                    temp.position(offset);
                    temp.get(ba);
                }
                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 {
                // Not cached: The returned buffer is small (shares its bytes with the bundle)
                // and usually quickly discarded after use.
                // Also, even a cached buffer would have to be cloned because it is mutable
                // (position & mark).
                offset=getResourceByteOffset(offset);
                length=getInt(offset);
                if(length == 0) {
                    return emptyByteBuffer.duplicate();
                }
                offset += 4;
                ByteBuffer result = bytes.duplicate();
                result.position(offset).limit(offset + length);
                result = ICUBinary.sliceWithOrder(result);
                if(!result.isReadOnly()) {
                    result = result.asReadOnlyBuffer();
                }
                return result;
            }
        } 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 {
                // Not cached: The array would have to be cloned anyway because
                // the cache must not be writable via the returned reference.
                offset=getResourceByteOffset(offset);
                length=getInt(offset);
                return getInts(offset+4, length);
            }
        } else {
            return null;
        }
    }

    private int getArrayLength(int res) {
        int offset = RES_GET_OFFSET(res);
        if(offset == 0) {
            return 0;
        }
        int type = RES_GET_TYPE(res);
        if(type == UResourceBundle.ARRAY) {
            offset = getResourceByteOffset(offset);
            return getInt(offset);
        } else if(type == ICUResourceBundle.ARRAY16) {
            return b16BitUnits.charAt(offset);
        } else {
            return 0;
        }
    }

    Array getArray(int res) {
        int type=RES_GET_TYPE(res);
        if(!URES_IS_ARRAY(type)) {
            return null;
        }
        int offset=RES_GET_OFFSET(res);
        if(offset == 0) {
            return EMPTY_ARRAY;
        }
        Object value = resourceCache.get(res);
        if(value != null) {
            return (Array)value;
        }
        Array array = (type == UResourceBundle.ARRAY) ?
                new Array32(this, offset) : new Array16(this, offset);
        return (Array)resourceCache.putIfAbsent(res, array, 0);
    }

    private int getTableLength(int res) {
        int offset = RES_GET_OFFSET(res);
        if(offset == 0) {
            return 0;
        }
        int type = RES_GET_TYPE(res);
        if(type == UResourceBundle.TABLE) {
            offset = getResourceByteOffset(offset);
            return bytes.getChar(offset);
        } else if(type == ICUResourceBundle.TABLE16) {
            return b16BitUnits.charAt(offset);
        } else if(type == ICUResourceBundle.TABLE32) {
            offset = getResourceByteOffset(offset);
            return getInt(offset);
        } else {
            return 0;
        }
    }

    Table getTable(int res) {
        int type = RES_GET_TYPE(res);
        if(!URES_IS_TABLE(type)) {
            return null;
        }
        int offset = RES_GET_OFFSET(res);
        if(offset == 0) {
            return EMPTY_TABLE;
        }
        Object value = resourceCache.get(res);
        if(value != null) {
            return (Table)value;
        }
        Table table;
        int size;  // Use size = 0 to never use SoftReferences for Tables?
        if(type == UResourceBundle.TABLE) {
            table = new Table1632(this, offset);
            size = table.getSize() * 2;
        } else if(type == ICUResourceBundle.TABLE16) {
            table = new Table16(this, offset);
            size = table.getSize() * 2;
        } else /* type == ICUResourceBundle.TABLE32 */ {
            table = new Table32(this, offset);
            size = table.getSize() * 4;
        }
        return (Table)resourceCache.putIfAbsent(res, table, size);
    }

    // ICUResource.Value --------------------------------------------------- ***

    /**
     * From C++ uresdata.c gPublicTypes[URES_LIMIT].
     */
    private static int PUBLIC_TYPES[] = {
        UResourceBundle.STRING,
        UResourceBundle.BINARY,
        UResourceBundle.TABLE,
        ICUResourceBundle.ALIAS,

        UResourceBundle.TABLE,     /* URES_TABLE32 */
        UResourceBundle.TABLE,     /* URES_TABLE16 */
        UResourceBundle.STRING,    /* URES_STRING_V2 */
        UResourceBundle.INT,

        UResourceBundle.ARRAY,
        UResourceBundle.ARRAY,     /* URES_ARRAY16 */
        UResourceBundle.NONE,
        UResourceBundle.NONE,

        UResourceBundle.NONE,
        UResourceBundle.NONE,
        UResourceBundle.INT_VECTOR,
        UResourceBundle.NONE
    };

    static class ReaderValue extends ICUResource.Value {
        ICUResourceBundleReader reader;
        private int res;

        @Override
        public int getType() {
            return PUBLIC_TYPES[RES_GET_TYPE(res)];
        }

        @Override
        public String getString() {
            String s = reader.getString(res);
            if (s == null) {
                throw new UResourceTypeMismatchException("");
            }
            return s;
        }

        @Override
        public int getInt() {
            if (RES_GET_TYPE(res) != UResourceBundle.INT) {
                throw new UResourceTypeMismatchException("");
            }
            return RES_GET_INT(res);
        }

        @Override
        public int getUInt() {
            if (RES_GET_TYPE(res) != UResourceBundle.INT) {
                throw new UResourceTypeMismatchException("");
            }
            return RES_GET_UINT(res);
        }

        @Override
        public int[] getIntVector() {
            int[] iv = reader.getIntVector(res);
            if (iv == null) {
                throw new UResourceTypeMismatchException("");
            }
            return iv;
        }

        @Override
        public ByteBuffer getBinary() {
            ByteBuffer bb = reader.getBinary(res);
            if (bb == null) {
                throw new UResourceTypeMismatchException("");
            }
            return bb;
        }
    }

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

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

        int getSize() {
            return size;
        }
        int getContainerResource(ICUResourceBundleReader reader, int index) {
            return ICUResourceBundle.RES_BOGUS;
        }
        protected int getContainer16Resource(ICUResourceBundleReader reader, int index) {
            if (index < 0 || size <= index) {
                return ICUResourceBundle.RES_BOGUS;
            }
            int res16 = reader.b16BitUnits.charAt(itemsOffset + index);
            if (res16 < reader.poolStringIndex16Limit) {
                // Pool string, nothing to do.
            } else {
                // Local string, adjust the 16-bit offset to a regular one,
                // with a larger pool string index limit.
                res16 = res16 - reader.poolStringIndex16Limit + reader.poolStringIndexLimit;
            }
            return (ICUResourceBundle.STRING_V2 << 28) | res16;
        }
        protected int getContainer32Resource(ICUResourceBundleReader reader, int index) {
            if (index < 0 || size <= index) {
                return ICUResourceBundle.RES_BOGUS;
            }
            return reader.getInt(itemsOffset + 4 * index);
        }
        int getResource(ICUResourceBundleReader reader, String resKey) {
            return getContainerResource(reader, Integer.parseInt(resKey));
        }
        Container() {
        }
    }
    static class Array extends Container {
        Array() {}
        void getAllItems(ICUResourceBundleReader reader,
                ICUResource.Key key, ReaderValue value, ArraySink sink) {
            for (int i = 0; i < size; ++i) {
                int res = getContainerResource(reader, i);
                int type = RES_GET_TYPE(res);
                if (URES_IS_ARRAY(type)) {
                    int numItems = reader.getArrayLength(res);
                    ArraySink subSink = sink.getOrCreateArraySink(i, numItems);
                    if (subSink != null) {
                        Array array = reader.getArray(res);
                        assert(array.size == numItems);
                        array.getAllItems(reader, key, value, subSink);
                    }
                } else if (URES_IS_TABLE(type)) {
                    int numItems = reader.getTableLength(res);
                    TableSink subSink = sink.getOrCreateTableSink(i, numItems);
                    if (subSink != null) {
                        Table table = reader.getTable(res);
                        assert(table.size == numItems);
                        table.getAllItems(reader, key, value, subSink);
                    }
                } else if (type == ICUResourceBundle.ALIAS) {
                    throw new UnsupportedOperationException(
                            "aliases not handled in resource enumeration");
                } else {
                    value.res = res;
                    sink.put(i, value);
                }
            }
        }
    }
    private static final class Array32 extends Array {
        @Override
        int getContainerResource(ICUResourceBundleReader reader, int index) {
            return getContainer32Resource(reader, index);
        }
        Array32(ICUResourceBundleReader reader, int offset) {
            offset = reader.getResourceByteOffset(offset);
            size = reader.getInt(offset);
            itemsOffset = offset + 4;
        }
    }
    private static final class Array16 extends Array {
        @Override
        int getContainerResource(ICUResourceBundleReader reader, int index) {
            return getContainer16Resource(reader, index);
        }
        Array16(ICUResourceBundleReader reader, int offset) {
            size = reader.b16BitUnits.charAt(offset);
            itemsOffset = offset + 1;
        }
    }
    static class Table extends Container {
        protected char[] keyOffsets;
        protected int[] key32Offsets;

        String getKey(ICUResourceBundleReader reader, 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(ICUResourceBundleReader reader, 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. */
        }
        @Override
        int getResource(ICUResourceBundleReader reader, String resKey) {
            return getContainerResource(reader, findTableItem(reader, resKey));
        }
        void getAllItems(ICUResourceBundleReader reader,
                ICUResource.Key key, ReaderValue value, TableSink sink) {
            for (int i = 0; i < size; ++i) {
                if (keyOffsets != null) {
                    reader.setKeyFromKey16(keyOffsets[i], key);
                } else {
                    reader.setKeyFromKey32(key32Offsets[i], key);
                }
                int res = getContainerResource(reader, i);
                int type = RES_GET_TYPE(res);
                if (URES_IS_ARRAY(type)) {
                    int numItems = reader.getArrayLength(res);
                    ArraySink subSink = sink.getOrCreateArraySink(key, numItems);
                    if (subSink != null) {
                        Array array = reader.getArray(res);
                        assert(array.size == numItems);
                        array.getAllItems(reader, key, value, subSink);
                    }
                } else if (URES_IS_TABLE(type)) {
                    int numItems = reader.getTableLength(res);
                    TableSink subSink = sink.getOrCreateTableSink(key, numItems);
                    if (subSink != null) {
                        Table table = reader.getTable(res);
                        assert(table.size == numItems);
                        table.getAllItems(reader, key, value, subSink);
                    }
                } else if (type == ICUResourceBundle.ALIAS) {
                    throw new UnsupportedOperationException(
                            "aliases not handled in resource enumeration");
                } else if (reader.isNoInheritanceMarker(res)) {
                    sink.putNoFallback(key);
                } else {
                    value.res = res;
                    sink.put(key, value);
                }
            }
        }
        Table() {
        }
    }
    private static final class Table1632 extends Table {
        @Override
        int getContainerResource(ICUResourceBundleReader reader, int index) {
            return getContainer32Resource(reader, index);
        }
        Table1632(ICUResourceBundleReader reader, int offset) {
            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 {
        @Override
        int getContainerResource(ICUResourceBundleReader reader, int index) {
            return getContainer16Resource(reader, index);
        }
        Table16(ICUResourceBundleReader reader, int offset) {
            keyOffsets = reader.getTable16KeyOffsets(offset);
            size = keyOffsets.length;
            itemsOffset = offset + 1 + size;
        }
    }
    private static final class Table32 extends Table {
        @Override
        int getContainerResource(ICUResourceBundleReader reader, int index) {
            return getContainer32Resource(reader, index);
        }
        Table32(ICUResourceBundleReader reader, int offset) {
            offset = reader.getResourceByteOffset(offset);
            key32Offsets = reader.getTable32KeyOffsets(offset);
            size = key32Offsets.length;
            itemsOffset = offset + 4 * (1 + size);
        }
    }

    // Resource cache ------------------------------------------------------ ***

    /**
     * Cache of some of one resource bundle's resources.
     * Avoids creating multiple Java objects for the same resource items,
     * including multiple copies of their contents.
     *
     * <p>Mutable objects must not be cached and then returned to the caller
     * because the cache must not be writable via the returned reference.
     *
     * <p>Resources are mapped by their resource integers.
     * Empty resources with offset 0 cannot be mapped.
     * Integers need not and should not be cached.
     * Multiple .res items may share resource offsets (genrb eliminates some duplicates).
     *
     * <p>This cache uses int[] and Object[] arrays to minimize object creation
     * and avoid auto-boxing.
     *
     * <p>Large resource objects are stored in SoftReferences.
     *
     * <p>For few resources, a small table is used with binary search.
     * When more resources are cached, then the data structure changes to be faster
     * but also use more memory.
     */
    private static final class ResourceCache {
        // Number of items to be stored in a simple array with binary search and insertion sort.
        private static final int SIMPLE_LENGTH = 32;

        // When more than SIMPLE_LENGTH items are cached,
        // then switch to a trie-like tree of levels with different array lengths.
        private static final int ROOT_BITS = 7;
        private static final int NEXT_BITS = 6;

        // Simple table, used when length >= 0.
        private int[] keys = new int[SIMPLE_LENGTH];
        private Object[] values = new Object[SIMPLE_LENGTH];
        private int length;

        // Trie-like tree of levels, used when length < 0.
        private int maxOffsetBits;
        /**
         * Number of bits in each level, each stored in a nibble.
         */
        private int levelBitsList;
        private Level rootLevel;

        @SuppressWarnings("unchecked")
        private static final Object putIfCleared(Object[] values, int index, Object item, int size) {
            Object value = values[index];
            if(!(value instanceof SoftReference)) {
                assert size < LARGE_SIZE;  // Caller should be consistent for each resource.
                return value;
            }
            assert size >= LARGE_SIZE;
            value = ((SoftReference<Object>)value).get();
            if(value != null) {
                return value;
            }
            values[index] = new SoftReference<Object>(item);
            return item;
        }

        private static final class Level {
            int levelBitsList;
            int shift;
            int mask;
            int[] keys;
            Object[] values;

            Level(int levelBitsList, int shift) {
                this.levelBitsList = levelBitsList;
                this.shift = shift;
                int bits = levelBitsList & 0xf;
                assert bits != 0;
                int length = 1 << bits;
                mask = length - 1;
                keys = new int[length];
                values = new Object[length];
            }

            Object get(int key) {
                int index = (key >> shift) & mask;
                int k = keys[index];
                if(k == key) {
                    return values[index];
                }
                if(k == 0) {
                    Level level = (Level)values[index];
                    if(level != null) {
                        return level.get(key);
                    }
                }
                return null;
            }

            Object putIfAbsent(int key, Object item, int size) {
                int index = (key >> shift) & mask;
                int k = keys[index];
                if(k == key) {
                    return putIfCleared(values, index, item, size);
                }
                if(k == 0) {
                    Level level = (Level)values[index];
                    if(level != null) {
                        return level.putIfAbsent(key, item, size);
                    }
                    keys[index] = key;
                    values[index] = (size >= LARGE_SIZE) ? new SoftReference<Object>(item) : item;
                    return item;
                }
                // Collision: Add a child level, move the old item there,
                // and then insert the current item.
                Level level = new Level(levelBitsList >> 4, shift + (levelBitsList & 0xf));
                int i = (k >> level.shift) & level.mask;
                level.keys[i] = k;
                level.values[i] = values[index];
                keys[index] = 0;
                values[index] = level;
                return level.putIfAbsent(key, item, size);
            }
        }

        ResourceCache(int maxOffset) {
            assert maxOffset != 0;
            maxOffsetBits = 28;
            while(maxOffset <= 0x7ffffff) {
                maxOffset <<= 1;
                --maxOffsetBits;
            }
            int keyBits = maxOffsetBits + 2;  // +2 for mini type: at most 30 bits used in a key
            // Precompute for each level the number of bits it handles.
            if(keyBits <= ROOT_BITS) {
                levelBitsList = keyBits;
            } else if(keyBits < (ROOT_BITS + 3)) {
                levelBitsList = 0x30 | (keyBits - 3);
            } else {
                levelBitsList = ROOT_BITS;
                keyBits -= ROOT_BITS;
                int shift = 4;
                for(;;) {
                    if(keyBits <= NEXT_BITS) {
                        levelBitsList |= keyBits << shift;
                        break;
                    } else if(keyBits < (NEXT_BITS + 3)) {
                        levelBitsList |= (0x30 | (keyBits - 3)) << shift;
                        break;
                    } else {
                        levelBitsList |= NEXT_BITS << shift;
                        keyBits -= NEXT_BITS;
                        shift += 4;
                    }
                }
            }
        }

        /**
         * Turns a resource integer (with unused bits in the middle)
         * into a key with fewer bits (at most keyBits).
         */
        private int makeKey(int res) {
            // It is possible for resources of different types in the 16-bit array
            // to share a start offset; distinguish between those with a 2-bit value,
            // as a tie-breaker in the bits just above the highest possible offset.
            // It is not possible for "regular" resources of different types
            // to share a start offset with each other,
            // but offsets for 16-bit and "regular" resources overlap;
            // use 2-bit value 0 for "regular" resources.
            int type = RES_GET_TYPE(res);
            int miniType =
                    (type == ICUResourceBundle.STRING_V2) ? 1 :
                        (type == ICUResourceBundle.TABLE16) ? 3 :
                            (type == ICUResourceBundle.ARRAY16) ? 2 : 0;
            return RES_GET_OFFSET(res) | (miniType << maxOffsetBits);
        }

        private int findSimple(int key) {
            // With Java 6, return Arrays.binarySearch(keys, 0, length, key).
            int start = 0;
            int limit = length;
            while((limit - start) > 8) {
                int mid = (start + limit) / 2;
                if(key < keys[mid]) {
                    limit = mid;
                } else {
                    start = mid;
                }
            }
            // For a small number of items, linear search should be a little faster.
            while(start < limit) {
                int k = keys[start];
                if(key < k) {
                    return ~start;
                }
                if(key == k) {
                    return start;
                }
                ++start;
            }
            return ~start;
        }

        @SuppressWarnings("unchecked")
        synchronized Object get(int res) {
            // Integers and empty resources need not be cached.
            // The cache itself uses res=0 for "no match".
            assert RES_GET_OFFSET(res) != 0;
            Object value;
            if(length >= 0) {
                int index = findSimple(res);
                if(index >= 0) {
                    value = values[index];
                } else {
                    return null;
                }
            } else {
                value = rootLevel.get(makeKey(res));
                if(value == null) {
                    return null;
                }
            }
            if(value instanceof SoftReference) {
                value = ((SoftReference<Object>)value).get();
            }
            return value;  // null if the reference was cleared
        }

        synchronized Object putIfAbsent(int res, Object item, int size) {
            if(length >= 0) {
                int index = findSimple(res);
                if(index >= 0) {
                    return putIfCleared(values, index, item, size);
                } else if(length < SIMPLE_LENGTH) {
                    index = ~index;
                    if(index < length) {
                        System.arraycopy(keys, index, keys, index + 1, length - index);
                        System.arraycopy(values, index, values, index + 1, length - index);
                    }
                    ++length;
                    keys[index] = res;
                    values[index] = (size >= LARGE_SIZE) ? new SoftReference<Object>(item) : item;
                    return item;
                } else /* not found && length == SIMPLE_LENGTH */ {
                    // Grow to become trie-like.
                    rootLevel = new Level(levelBitsList, 0);
                    for(int i = 0; i < SIMPLE_LENGTH; ++i) {
                        rootLevel.putIfAbsent(makeKey(keys[i]), values[i], 0);
                    }
                    keys = null;
                    values = null;
                    length = -1;
                }
            }
            return rootLevel.putIfAbsent(makeKey(res), item, 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;
                }
            }
        }
    }
}
