12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others.
22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*******************************************************************************
5f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert* Copyright (C) 2013-2015, International Business Machines
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Corporation and others.  All Rights Reserved.
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*******************************************************************************
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* CollationTailoring.java, ported from collationtailoring.h/.cpp
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* C++ version created on: 2013mar12
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* created by: Markus W. Scherer
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.impl.coll;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Norm2AllModes;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Normalizer2Impl;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Trie2_32;
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UnicodeSet;
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale;
23bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.ibm.icu.util.UResourceBundle;
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.VersionInfo;
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Collation tailoring data & settings.
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is a container of values for a collation tailoring
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * built from rules or deserialized from binary data.
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is logically immutable: Do not modify its values.
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The fields are public for convenience.
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic final class CollationTailoring {
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    CollationTailoring(SharedObject.Reference<CollationSettings> baseSettings) {
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(baseSettings != null) {
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            assert(baseSettings.readOnly().reorderCodes.length == 0);
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            assert(baseSettings.readOnly().reorderTable == null);
39f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert            assert(baseSettings.readOnly().minHighNoReorder == 0);
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            settings = baseSettings.clone();
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            settings = new SharedObject.Reference<CollationSettings>(new CollationSettings());
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    void ensureOwnedData() {
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(ownedData == null) {
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Normalizer2Impl nfcImpl = Norm2AllModes.getNFCInstance().impl;
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ownedData = new CollationData(nfcImpl);
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        data = ownedData;
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    /** Not thread-safe, call only before sharing. */
55bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void setRules(String r) {
56bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        assert rules == null && rulesResource == null;
57bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        rules = r;
58bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
59bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    /** Not thread-safe, call only before sharing. */
60bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    void setRulesResource(UResourceBundle res) {
61bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        assert rules == null && rulesResource == null;
62bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        rulesResource = res;
63bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
64bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public String getRules() {
65bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (rules != null) {
66bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return rules;
67bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
68bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (rulesResource != null) {
69bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return rulesResource.getString();
70bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
71bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return "";
72bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
73bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static VersionInfo makeBaseVersion(VersionInfo ucaVersion) {
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return VersionInfo.getInstance(
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                VersionInfo.UCOL_BUILDER_VERSION.getMajor(),
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                (ucaVersion.getMajor() << 3) + ucaVersion.getMinor(),
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ucaVersion.getMilli() << 6,
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0);
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    void setVersion(int baseVersion, int rulesVersion) {
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // See comments for version field.
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int r = (rulesVersion >> 16) & 0xff00;
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int s = (rulesVersion >> 16) & 0xff;
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int t = (rulesVersion >> 8) & 0xff;
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int q = rulesVersion & 0xff;
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        version = (VersionInfo.UCOL_BUILDER_VERSION.getMajor() << 24) |
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                (baseVersion & 0xffc000) |  // UCA version u.v.w
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ((r + (r >> 6)) & 0x3f00) |
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                (((s << 3) + (s >> 5) + t + (q << 4) + (q >> 4)) & 0xff);
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    int getUCAVersion() {
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Version second byte/bits 23..16 to bits 11..4,
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // third byte/bits 15..14 to bits 1..0.
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return ((version >> 12) & 0xff0) | ((version >> 14) & 3);
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // data for sorting etc.
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public CollationData data;  // == base data or ownedData
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public SharedObject.Reference<CollationSettings> settings;  // reference-counted
101bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // In Java, deserialize the rules string from the resource bundle
102bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // only when it is used. (It can be large and is rarely used.)
103bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private String rules;
104bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private UResourceBundle rulesResource;
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // The locale is null (C++: bogus) when built from rules or constructed from a binary blob.
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // It can then be set by the service registration code which is thread-safe.
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public ULocale actualLocale = ULocale.ROOT;
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // UCA version u.v.w & rules version r.s.t.q:
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // version[0]: builder version (runtime version is mixed in at runtime)
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // version[1]: bits 7..3=u, bits 2..0=v
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // version[2]: bits 7..6=w, bits 5..0=r
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // version[3]= (s<<5)+(s>>3)+t+(q<<4)+(q>>4)
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int version = 0;
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // owned objects
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    CollationData ownedData;
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Trie2_32 trie;
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    UnicodeSet unsafeBackwardSet;
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Map<Integer, Integer> maxExpansions;
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Not Cloneable: A CollationTailoring cannot be copied.
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * It is immutable, and the data trie cannot be copied either.
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
126