12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
22ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
32ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller **********************************************************************
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (c) 2002-2015, International Business Machines
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Corporation and others.  All Rights Reserved.
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller **********************************************************************
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Author: Alan Liu
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Created: November 5 2002
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Since: ICU 2.4
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 2010nov19 Markus Scherer  Rewrite for formatVersion 2.
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller **********************************************************************
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.impl;
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.io.IOException;
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.nio.ByteBuffer;
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.MissingResourceException;
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.lang.UProperty;
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.BytesTrie;
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Wrapper for the pnames.icu binary data file.  This data file is
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * imported from icu4c.  It contains property and property value
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * aliases from the UCD files PropertyAliases.txt and
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * PropertyValueAliases.txt.  The file is built by the icu4c tool
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * genpname.  It must be an ASCII big-endian file to be
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * usable in icu4j.
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This class performs two functions.
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * (1) It can import the flat binary data into usable objects.
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * (2) It provides an API to access the tree of objects.
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Needless to say, this class is tightly coupled to the binary format
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of icu4c's pnames.icu file.
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Each time a UPropertyAliases is constructed, the pnames.icu file is
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * read, parsed, and data structures assembled.  Clients should create one
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * singleton instance and cache it.
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @author Alan Liu
45836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic final class UPropertyAliases {
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // Byte offsets from the start of the data, after the generic header.
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int IX_VALUE_MAPS_OFFSET=0;
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int IX_BYTE_TRIES_OFFSET=1;
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int IX_NAME_GROUPS_OFFSET=2;
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int IX_RESERVED3_OFFSET=3;
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // private static final int IX_RESERVED4_OFFSET=4;
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // private static final int IX_TOTAL_SIZE=5;
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // Other values.
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // private static final int IX_MAX_NAME_LENGTH=6;
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // private static final int IX_RESERVED7=7;
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // private static final int IX_COUNT=8;
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //----------------------------------------------------------------
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // Runtime data.  This is an unflattened representation of the
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // data in pnames.icu.
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int[] valueMaps;
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private byte[] bytesTries;
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private String nameGroups;
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final class IsAcceptable implements ICUBinary.Authenticate {
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // @Override when we switch to Java 6
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public boolean isDataVersionAcceptable(byte version[]) {
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return version[0]==2;
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final IsAcceptable IS_ACCEPTABLE=new IsAcceptable();
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int DATA_FORMAT=0x706E616D;  // "pnam"
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private void load(ByteBuffer bytes) throws IOException {
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        //dataVersion=ICUBinary.readHeaderAndDataVersion(bytes, DATA_FORMAT, IS_ACCEPTABLE);
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ICUBinary.readHeader(bytes, DATA_FORMAT, IS_ACCEPTABLE);
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int indexesLength=bytes.getInt()/4;  // inIndexes[IX_VALUE_MAPS_OFFSET]/4
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(indexesLength<8) {  // formatVersion 2 initially has 8 indexes
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IOException("pnames.icu: not enough indexes");
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int[] inIndexes=new int[indexesLength];
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        inIndexes[0]=indexesLength*4;
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int i=1; i<indexesLength; ++i) {
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            inIndexes[i]=bytes.getInt();
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Read the valueMaps.
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int offset=inIndexes[IX_VALUE_MAPS_OFFSET];
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int nextOffset=inIndexes[IX_BYTE_TRIES_OFFSET];
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int numInts=(nextOffset-offset)/4;
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        valueMaps=ICUBinary.getInts(bytes, numInts, 0);
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Read the bytesTries.
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        offset=nextOffset;
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        nextOffset=inIndexes[IX_NAME_GROUPS_OFFSET];
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int numBytes=nextOffset-offset;
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        bytesTries=new byte[numBytes];
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        bytes.get(bytesTries);
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Read the nameGroups and turn them from ASCII bytes into a Java String.
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        offset=nextOffset;
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        nextOffset=inIndexes[IX_RESERVED3_OFFSET];
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        numBytes=nextOffset-offset;
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        StringBuilder sb=new StringBuilder(numBytes);
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int i=0; i<numBytes; ++i) {
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            sb.append((char)bytes.get());
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        nameGroups=sb.toString();
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private UPropertyAliases() throws IOException {
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ByteBuffer bytes = ICUBinary.getRequiredData("pnames.icu");
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        load(bytes);
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int findProperty(int property) {
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int i=1;  // valueMaps index, initially after numRanges
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int numRanges=valueMaps[0]; numRanges>0; --numRanges) {
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Read and skip the start and limit of this range.
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int start=valueMaps[i];
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int limit=valueMaps[i+1];
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            i+=2;
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(property<start) {
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(property<limit) {
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return i+(property-start)*2;
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            i+=(limit-start)*2;  // Skip all entries for this range.
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return 0;
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int findPropertyValueNameGroup(int valueMapIndex, int value) {
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(valueMapIndex==0) {
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 0;  // The property does not have named values.
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ++valueMapIndex;  // Skip the BytesTrie offset.
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int numRanges=valueMaps[valueMapIndex++];
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(numRanges<0x10) {
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Ranges of values.
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for(; numRanges>0; --numRanges) {
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // Read and skip the start and limit of this range.
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int start=valueMaps[valueMapIndex];
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int limit=valueMaps[valueMapIndex+1];
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                valueMapIndex+=2;
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(value<start) {
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    break;
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(value<limit) {
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    return valueMaps[valueMapIndex+value-start];
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                valueMapIndex+=limit-start;  // Skip all entries for this range.
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // List of values.
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int valuesStart=valueMapIndex;
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int nameGroupOffsetsStart=valueMapIndex+numRanges-0x10;
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            do {
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int v=valueMaps[valueMapIndex];
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(value<v) {
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    break;
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(value==v) {
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    return valueMaps[nameGroupOffsetsStart+valueMapIndex-valuesStart];
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } while(++valueMapIndex<nameGroupOffsetsStart);
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return 0;
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private String getName(int nameGroupsIndex, int nameIndex) {
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int numNames=nameGroups.charAt(nameGroupsIndex++);
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(nameIndex<0 || numNames<=nameIndex) {
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalIcuArgumentException("Invalid property (value) name choice");
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Skip nameIndex names.
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(; nameIndex>0; --nameIndex) {
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            while(0!=nameGroups.charAt(nameGroupsIndex++)) {}
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Find the end of this name.
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int nameStart=nameGroupsIndex;
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        while(0!=nameGroups.charAt(nameGroupsIndex)) {
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ++nameGroupsIndex;
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(nameStart==nameGroupsIndex) {
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return null;  // no name (Property[Value]Aliases.txt has "n/a")
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return nameGroups.substring(nameStart, nameGroupsIndex);
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int asciiToLowercase(int c) {
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return 'A'<=c && c<='Z' ? c+0x20 : c;
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private boolean containsName(BytesTrie trie, CharSequence name) {
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        BytesTrie.Result result=BytesTrie.Result.NO_VALUE;
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int i=0; i<name.length(); ++i) {
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int c=name.charAt(i);
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Ignore delimiters '-', '_', and ASCII White_Space.
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(c=='-' || c=='_' || c==' ' || (0x09<=c && c<=0x0d)) {
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                continue;
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(!result.hasNext()) {
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return false;
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            c=asciiToLowercase(c);
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            result=trie.next(c);
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result.hasValue();
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //----------------------------------------------------------------
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // Public API
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final UPropertyAliases INSTANCE;
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static {
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        try {
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            INSTANCE = new UPropertyAliases();
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } catch(IOException e) {
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ///CLOVER:OFF
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            MissingResourceException mre = new MissingResourceException(
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    "Could not construct UPropertyAliases. Missing pnames.icu", "", "");
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            mre.initCause(e);
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw mre;
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ///CLOVER:ON
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns a property name given a property enum.
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Multiple names may be available for each property;
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * the nameChoice selects among them.
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String getPropertyName(int property, int nameChoice) {
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int valueMapIndex=findProperty(property);
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(valueMapIndex==0) {
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException(
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    "Invalid property enum "+property+" (0x"+Integer.toHexString(property)+")");
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getName(valueMaps[valueMapIndex], nameChoice);
2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns a value name given a property enum and a value enum.
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Multiple names may be available for each value;
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * the nameChoice selects among them.
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String getPropertyValueName(int property, int value, int nameChoice) {
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int valueMapIndex=findProperty(property);
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(valueMapIndex==0) {
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException(
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    "Invalid property enum "+property+" (0x"+Integer.toHexString(property)+")");
2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int nameGroupOffset=findPropertyValueNameGroup(valueMaps[valueMapIndex+1], value);
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(nameGroupOffset==0) {
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException(
2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    "Property "+property+" (0x"+Integer.toHexString(property)+
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    ") does not have named values");
2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getName(nameGroupOffset, nameChoice);
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int getPropertyOrValueEnum(int bytesTrieOffset, CharSequence alias) {
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        BytesTrie trie=new BytesTrie(bytesTries, bytesTrieOffset);
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(containsName(trie, alias)) {
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return trie.getValue();
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return UProperty.UNDEFINED;
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns a property enum given one of its property names.
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If the property name is not known, this method returns
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * UProperty.UNDEFINED.
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int getPropertyEnum(CharSequence alias) {
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getPropertyOrValueEnum(0, alias);
2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns a value enum given a property enum and one of its value names.
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int getPropertyValueEnum(int property, CharSequence alias) {
2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int valueMapIndex=findProperty(property);
2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(valueMapIndex==0) {
2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException(
2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    "Invalid property enum "+property+" (0x"+Integer.toHexString(property)+")");
2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        valueMapIndex=valueMaps[valueMapIndex+1];
2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(valueMapIndex==0) {
2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException(
2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    "Property "+property+" (0x"+Integer.toHexString(property)+
3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    ") does not have named values");
3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // valueMapIndex is the start of the property's valueMap,
3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // where the first word is the BytesTrie offset.
3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getPropertyOrValueEnum(valueMaps[valueMapIndex], alias);
3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns a value enum given a property enum and one of its value names. Does not throw.
3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return value enum, or UProperty.UNDEFINED if not defined for that property
3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int getPropertyValueEnumNoThrow(int property, CharSequence alias) {
3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int valueMapIndex=findProperty(property);
3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(valueMapIndex==0) {
3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return UProperty.UNDEFINED;
3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        valueMapIndex=valueMaps[valueMapIndex+1];
3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(valueMapIndex==0) {
3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return UProperty.UNDEFINED;
3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // valueMapIndex is the start of the property's valueMap,
3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // where the first word is the BytesTrie offset.
3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getPropertyOrValueEnum(valueMaps[valueMapIndex], alias);
3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Compare two property names, returning <0, 0, or >0.  The
3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * comparison is that described as "loose" matching in the
3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Property*Aliases.txt files.
3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static int compare(String stra, String strb) {
3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Note: This implementation is a literal copy of
3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // uprv_comparePropertyNames.  It can probably be improved.
3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int istra=0, istrb=0, rc;
3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int cstra=0, cstrb=0;
3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (;;) {
3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            /* Ignore delimiters '-', '_', and ASCII White_Space */
3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            while (istra<stra.length()) {
3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                cstra = stra.charAt(istra);
3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                switch (cstra) {
3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                case '-':  case '_':  case ' ':  case '\t':
3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                case '\n': case 0xb/*\v*/: case '\f': case '\r':
3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    ++istra;
3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    continue;
3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            while (istrb<strb.length()) {
3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                cstrb = strb.charAt(istrb);
3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                switch (cstrb) {
3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                case '-':  case '_':  case ' ':  case '\t':
3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                case '\n': case 0xb/*\v*/: case '\f': case '\r':
3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    ++istrb;
3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    continue;
3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
3572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            /* If we reach the ends of both strings then they match */
3602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            boolean endstra = istra==stra.length();
3612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            boolean endstrb = istrb==strb.length();
3622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (endstra) {
3632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (endstrb) return 0;
3642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                cstra = 0;
3652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else if (endstrb) {
3662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                cstrb = 0;
3672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            rc = asciiToLowercase(cstra) - asciiToLowercase(cstrb);
3702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (rc != 0) {
3712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return rc;
3722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ++istra;
3752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ++istrb;
3762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
379