196b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes/*
296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * Copyright (C) 2010 The Android Open Source Project
3f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
496b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
596b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * you may not use this file except in compliance with the License.
696b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * You may obtain a copy of the License at
7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
896b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
1096b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * Unless required by applicable law or agreed to in writing, software
1196b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * See the License for the specific language governing permissions and
1496b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * limitations under the License.
1596b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes */
1696b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes
1796b251cd6e3aa354b86330da0c598d538151be0aElliott Hughespackage java.lang;
1896b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes
19728029941ba340aeb8e4098b7ad12d3a30e38aa9Neil Fullerimport android.icu.text.Transliterator;
2096b251cd6e3aa354b86330da0c598d538151be0aElliott Hughesimport java.util.Locale;
21162b0775772fa66b7eb634760a8159a60c1ddceaElliott Hughesimport libcore.icu.ICU;
2296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes
2396b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes/**
2496b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes * Performs case operations as described by http://unicode.org/reports/tr21/tr21-5.html.
2596b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes */
2696b251cd6e3aa354b86330da0c598d538151be0aElliott Hughesclass CaseMapper {
279de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes    private static final char[] upperValues = "SS\u0000\u02bcN\u0000J\u030c\u0000\u0399\u0308\u0301\u03a5\u0308\u0301\u0535\u0552\u0000H\u0331\u0000T\u0308\u0000W\u030a\u0000Y\u030a\u0000A\u02be\u0000\u03a5\u0313\u0000\u03a5\u0313\u0300\u03a5\u0313\u0301\u03a5\u0313\u0342\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1fba\u0399\u0000\u0391\u0399\u0000\u0386\u0399\u0000\u0391\u0342\u0000\u0391\u0342\u0399\u0391\u0399\u0000\u1fca\u0399\u0000\u0397\u0399\u0000\u0389\u0399\u0000\u0397\u0342\u0000\u0397\u0342\u0399\u0397\u0399\u0000\u0399\u0308\u0300\u0399\u0308\u0301\u0399\u0342\u0000\u0399\u0308\u0342\u03a5\u0308\u0300\u03a5\u0308\u0301\u03a1\u0313\u0000\u03a5\u0342\u0000\u03a5\u0308\u0342\u1ffa\u0399\u0000\u03a9\u0399\u0000\u038f\u0399\u0000\u03a9\u0342\u0000\u03a9\u0342\u0399\u03a9\u0399\u0000FF\u0000FI\u0000FL\u0000FFIFFLST\u0000ST\u0000\u0544\u0546\u0000\u0544\u0535\u0000\u0544\u053b\u0000\u054e\u0546\u0000\u0544\u053d\u0000".toCharArray();
289de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes    private static final char[] upperValues2 = "\u000b\u0000\f\u0000\r\u0000\u000e\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-./0123456789:;<=>\u0000\u0000?@A\u0000BC\u0000\u0000\u0000\u0000D\u0000\u0000\u0000\u0000\u0000EFG\u0000HI\u0000\u0000\u0000\u0000J\u0000\u0000\u0000\u0000\u0000KL\u0000\u0000MN\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000OPQ\u0000RS\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000TUV\u0000WX\u0000\u0000\u0000\u0000Y".toCharArray();
29f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
3096b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    private static final char LATIN_CAPITAL_I_WITH_DOT = '\u0130';
3196b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    private static final char GREEK_CAPITAL_SIGMA = '\u03a3';
3296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    private static final char GREEK_SMALL_FINAL_SIGMA = '\u03c2';
33f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
3496b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    /**
3596b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes     * Our current GC makes short-lived objects more expensive than we'd like. When that's fixed,
3696b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes     * this class should be changed so that you instantiate it with the String and its value,
3783c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao     * and count fields.
3896b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes     */
3996b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    private CaseMapper() {
4096b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    }
41f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
4296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    /**
4383c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao     * Implements String.toLowerCase. The original String instance is returned if nothing changes.
4496b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes     */
4583c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao    public static String toLowerCase(Locale locale, String s) {
469de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        // Punt hard cases to ICU4C.
47a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes        // Note that Greek isn't a particularly hard case for toLowerCase, only toUpperCase.
4896b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        String languageCode = locale.getLanguage();
499de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) {
50a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes            return ICU.toLowerCase(s, locale);
519de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        }
52f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
53b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko        char[] newValue = null;
5483c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao        for (int i = 0, end = s.length(); i < end; ++i) {
5583c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao            char ch = s.charAt(i);
562fc5dcd5614f910f25d794d272834752a72e63b1Elliott Hughes            char newCh;
579de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            if (ch == LATIN_CAPITAL_I_WITH_DOT || Character.isHighSurrogate(ch)) {
589de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                // Punt these hard cases.
59a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes                return ICU.toLowerCase(s, locale);
6083c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao            } else if (ch == GREEK_CAPITAL_SIGMA && isFinalSigma(s, i)) {
6196b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes                newCh = GREEK_SMALL_FINAL_SIGMA;
6296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes            } else {
6396b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes                newCh = Character.toLowerCase(ch);
6496b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes            }
6583c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao            if (ch != newCh) {
66b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                if (newValue == null) {
67b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                    newValue = new char[end];
68b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                    s.getCharsNoCheck(0, end, newValue, 0);
6983c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao                }
70b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                newValue[i] = newCh;
7196b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes            }
7296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        }
73b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko        return newValue != null ? new String(newValue) : s;
7496b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    }
75f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
7696b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    /**
7796b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes     * True if 'index' is preceded by a sequence consisting of a cased letter and a case-ignorable
7896b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes     * sequence, and 'index' is not followed by a sequence consisting of an ignorable sequence and
7996b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes     * then a cased letter.
8096b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes     */
8183c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao    private static boolean isFinalSigma(String s, int index) {
8296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        // TODO: we don't skip case-ignorable sequences like we should.
8396b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        // TODO: we should add a more direct way to test for a cased letter.
8483c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao        if (index <= 0) {
8596b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes            return false;
8696b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        }
8783c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao        char previous = s.charAt(index - 1);
8896b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        if (!(Character.isLowerCase(previous) || Character.isUpperCase(previous) || Character.isTitleCase(previous))) {
8996b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes            return false;
9096b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        }
9183c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao        if (index + 1 >= s.length()) {
9296b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes            return true;
9396b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        }
9483c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao        char next = s.charAt(index + 1);
9596b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        if (Character.isLowerCase(next) || Character.isUpperCase(next) || Character.isTitleCase(next)) {
9696b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes            return false;
9796b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        }
9896b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes        return true;
9996b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes    }
100f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
1019de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes    /**
1029de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes     * Return the index of the specified character into the upperValues table.
1039de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes     * The upperValues table contains three entries at each position. These
1049de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes     * three characters are the upper case conversion. If only two characters
1059de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes     * are used, the third character in the table is \u0000.
1069de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes     * @return the index into the upperValues table, or -1
1079de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes     */
1089de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes    private static int upperIndex(int ch) {
1099de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        int index = -1;
1109de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        if (ch >= 0xdf) {
1119de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            if (ch <= 0x587) {
1129de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                switch (ch) {
1139de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                case 0xdf: return 0;
1149de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                case 0x149: return 1;
1159de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                case 0x1f0: return 2;
1169de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                case 0x390: return 3;
1179de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                case 0x3b0: return 4;
1189de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                case 0x587: return 5;
1199de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                }
1209de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            } else if (ch >= 0x1e96) {
1219de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                if (ch <= 0x1e9a) {
1229de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    index = 6 + ch - 0x1e96;
1239de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                } else if (ch >= 0x1f50 && ch <= 0x1ffc) {
1249de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    index = upperValues2[ch - 0x1f50];
1259de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    if (index == 0) {
1269de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                        index = -1;
1279de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    }
1289de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                } else if (ch >= 0xfb00) {
1299de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    if (ch <= 0xfb06) {
1309de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                        index = 90 + ch - 0xfb00;
1319de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    } else if (ch >= 0xfb13 && ch <= 0xfb17) {
1329de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                        index = 97 + ch - 0xfb13;
1339de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    }
1349de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                }
1359de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            }
1369de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        }
1379de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        return index;
1389de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes    }
139f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
140a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes    private static final ThreadLocal<Transliterator> EL_UPPER = new ThreadLocal<Transliterator>() {
141a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes        @Override protected Transliterator initialValue() {
14217552b6592aeaaa564725a07e10e8c4b1c8163cbRayhaan Jaufeerally            return Transliterator.getInstance("el-Upper");
143a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes        }
144a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes    };
145a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes
14683c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao    public static String toUpperCase(Locale locale, String s, int count) {
1479de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        String languageCode = locale.getLanguage();
1489de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) {
149a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes            return ICU.toUpperCase(s, locale);
1509de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        }
151a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes        if (languageCode.equals("el")) {
152a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes            return EL_UPPER.get().transliterate(s);
153a2f8e8a253a93c8df8b0e6f458f4c573d48b9ed9Elliott Hughes        }
154f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
1559de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        char[] output = null;
1569de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        int i = 0;
157b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko        for (int o = 0; o < count; o++) {
15883c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao            char ch = s.charAt(o);
1599de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            if (Character.isHighSurrogate(ch)) {
160a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes                return ICU.toUpperCase(s, locale);
1619de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            }
1629de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            int index = upperIndex(ch);
1639de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            if (index == -1) {
1649de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                if (output != null && i >= output.length) {
1659de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    char[] newoutput = new char[output.length + (count / 6) + 2];
1669de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    System.arraycopy(output, 0, newoutput, 0, output.length);
1679de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    output = newoutput;
1689de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                }
1699de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                char upch = Character.toUpperCase(ch);
17083c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao                if (output != null) {
1719de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    output[i++] = upch;
17283c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao                } else if (ch != upch) {
173b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                    output = new char[count];
174b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                    i = o;
175b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                    s.getCharsNoCheck(0, i, output, 0);
176b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                    output[i++] = upch;
1779de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                }
1789de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            } else {
1799de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                int target = index * 3;
1809de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                char val3 = upperValues[target + 2];
1819de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                if (output == null) {
1829de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    output = new char[count + (count / 6) + 2];
18383c7414449bc406b581f0cb81ae06e7bce91403cJeff Hao                    i = o;
184b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko                    s.getCharsNoCheck(0, i, output, 0);
1859de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                } else if (i + (val3 == 0 ? 1 : 2) >= output.length) {
1869de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    char[] newoutput = new char[output.length + (count / 6) + 3];
1879de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    System.arraycopy(output, 0, newoutput, 0, output.length);
1889de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    output = newoutput;
1899de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                }
190f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
1919de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                char val = upperValues[target];
1929de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                output[i++] = val;
1939de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                val = upperValues[target + 1];
1949de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                output[i++] = val;
1959de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                if (val3 != 0) {
1969de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                    output[i++] = val3;
1979de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes                }
1989de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes            }
1999de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        }
2009de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        if (output == null) {
201b07812780bdb1aee50fae61cfa5f42be10dc8cfbVladimir Marko            return s;
2029de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        }
2039de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes        return output.length == i || output.length - i < 8 ? new String(0, i, output) : new String(output, 0, i);
2049de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes    }
20596b251cd6e3aa354b86330da0c598d538151be0aElliott Hughes}
206