12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*******************************************************************************
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*   Copyright (C) 2009-2014, International Business Machines
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*   Corporation and others.  All Rights Reserved.
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*******************************************************************************
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*/
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.text;
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.io.IOException;
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.ICUUncheckedIOException;
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Normalization filtered by a UnicodeSet.
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Normalizes portions of the text contained in the filter set and leaves
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * portions not contained in the filter set unchanged.
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Filtering is done via UnicodeSet.span(..., UnicodeSet.SpanCondition.SIMPLE).
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Not-in-the-filter text is treated as "is normalized" and "quick check yes".
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This class implements all of (and only) the Normalizer2 API.
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * An instance of this class is unmodifiable/immutable.
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @author Markus W. Scherer
25836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic class FilteredNormalizer2 extends Normalizer2 {
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Constructs a filtered normalizer wrapping any Normalizer2 instance
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * and a filter set.
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Both are aliased and must not be modified or deleted while this object
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * is used.
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The filter set should be frozen; otherwise the performance will suffer greatly.
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param n2 wrapped Normalizer2 instance
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param filterSet UnicodeSet which determines the characters to be normalized
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public FilteredNormalizer2(Normalizer2 n2, UnicodeSet filterSet) {
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        norm2=n2;
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        set=filterSet;
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public StringBuilder normalize(CharSequence src, StringBuilder dest) {
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(dest==src) {
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException();
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        dest.setLength(0);
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        normalize(src, dest, UnicodeSet.SpanCondition.SIMPLE);
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return dest;
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Appendable normalize(CharSequence src, Appendable dest) {
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(dest==src) {
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException();
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return normalize(src, dest, UnicodeSet.SpanCondition.SIMPLE);
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public StringBuilder normalizeSecondAndAppend(
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            StringBuilder first, CharSequence second) {
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return normalizeSecondAndAppend(first, second, true);
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public StringBuilder append(StringBuilder first, CharSequence second) {
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return normalizeSecondAndAppend(first, second, false);
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String getDecomposition(int c) {
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return set.contains(c) ? norm2.getDecomposition(c) : null;
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String getRawDecomposition(int c) {
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return set.contains(c) ? norm2.getRawDecomposition(c) : null;
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int composePair(int a, int b) {
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return (set.contains(a) && set.contains(b)) ? norm2.composePair(a, b) : -1;
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int getCombiningClass(int c) {
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return set.contains(c) ? norm2.getCombiningClass(c) : 0;
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean isNormalized(CharSequence s) {
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        UnicodeSet.SpanCondition spanCondition=UnicodeSet.SpanCondition.SIMPLE;
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int prevSpanLimit=0; prevSpanLimit<s.length();) {
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int spanLimit=set.span(s, prevSpanLimit, spanCondition);
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(spanCondition==UnicodeSet.SpanCondition.NOT_CONTAINED) {
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spanCondition=UnicodeSet.SpanCondition.SIMPLE;
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(!norm2.isNormalized(s.subSequence(prevSpanLimit, spanLimit))) {
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    return false;
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spanCondition=UnicodeSet.SpanCondition.NOT_CONTAINED;
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            prevSpanLimit=spanLimit;
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return true;
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Normalizer.QuickCheckResult quickCheck(CharSequence s) {
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Normalizer.QuickCheckResult result=Normalizer.YES;
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        UnicodeSet.SpanCondition spanCondition=UnicodeSet.SpanCondition.SIMPLE;
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int prevSpanLimit=0; prevSpanLimit<s.length();) {
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int spanLimit=set.span(s, prevSpanLimit, spanCondition);
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(spanCondition==UnicodeSet.SpanCondition.NOT_CONTAINED) {
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spanCondition=UnicodeSet.SpanCondition.SIMPLE;
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                Normalizer.QuickCheckResult qcResult=
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    norm2.quickCheck(s.subSequence(prevSpanLimit, spanLimit));
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(qcResult==Normalizer.NO) {
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    return qcResult;
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else if(qcResult==Normalizer.MAYBE) {
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    result=qcResult;
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spanCondition=UnicodeSet.SpanCondition.NOT_CONTAINED;
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            prevSpanLimit=spanLimit;
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result;
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int spanQuickCheckYes(CharSequence s) {
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        UnicodeSet.SpanCondition spanCondition=UnicodeSet.SpanCondition.SIMPLE;
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int prevSpanLimit=0; prevSpanLimit<s.length();) {
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int spanLimit=set.span(s, prevSpanLimit, spanCondition);
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(spanCondition==UnicodeSet.SpanCondition.NOT_CONTAINED) {
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spanCondition=UnicodeSet.SpanCondition.SIMPLE;
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int yesLimit=
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    prevSpanLimit+
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    norm2.spanQuickCheckYes(s.subSequence(prevSpanLimit, spanLimit));
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(yesLimit<spanLimit) {
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    return yesLimit;
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spanCondition=UnicodeSet.SpanCondition.NOT_CONTAINED;
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            prevSpanLimit=spanLimit;
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return s.length();
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean hasBoundaryBefore(int c) {
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return !set.contains(c) || norm2.hasBoundaryBefore(c);
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean hasBoundaryAfter(int c) {
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return !set.contains(c) || norm2.hasBoundaryAfter(c);
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean isInert(int c) {
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return !set.contains(c) || norm2.isInert(c);
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // Internal: No argument checking, and appends to dest.
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // Pass as input spanCondition the one that is likely to yield a non-zero
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // span length at the start of src.
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // For set=[:age=3.2:], since almost all common characters were in Unicode 3.2,
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // UnicodeSet.SpanCondition.SIMPLE should be passed in for the start of src
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // and UnicodeSet.SpanCondition.NOT_CONTAINED should be passed in if we continue after
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // an in-filter prefix.
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private Appendable normalize(CharSequence src, Appendable dest,
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                 UnicodeSet.SpanCondition spanCondition) {
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Don't throw away destination buffer between iterations.
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        StringBuilder tempDest=new StringBuilder();
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        try {
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for(int prevSpanLimit=0; prevSpanLimit<src.length();) {
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int spanLimit=set.span(src, prevSpanLimit, spanCondition);
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int spanLength=spanLimit-prevSpanLimit;
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(spanCondition==UnicodeSet.SpanCondition.NOT_CONTAINED) {
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(spanLength!=0) {
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest.append(src, prevSpanLimit, spanLimit);
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    spanCondition=UnicodeSet.SpanCondition.SIMPLE;
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(spanLength!=0) {
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        // Not norm2.normalizeSecondAndAppend() because we do not want
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        // to modify the non-filter part of dest.
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest.append(norm2.normalize(src.subSequence(prevSpanLimit, spanLimit), tempDest));
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    spanCondition=UnicodeSet.SpanCondition.NOT_CONTAINED;
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                prevSpanLimit=spanLimit;
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } catch(IOException e) {
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new ICUUncheckedIOException(e);
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return dest;
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private StringBuilder normalizeSecondAndAppend(StringBuilder first, CharSequence second,
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                                   boolean doNormalize) {
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(first==second) {
2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException();
2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(first.length()==0) {
2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(doNormalize) {
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return normalize(second, first);
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return first.append(second);
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // merge the in-filter suffix of the first string with the in-filter prefix of the second
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int prefixLimit=set.span(second, 0, UnicodeSet.SpanCondition.SIMPLE);
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(prefixLimit!=0) {
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            CharSequence prefix=second.subSequence(0, prefixLimit);
2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int suffixStart=set.spanBack(first, 0x7fffffff, UnicodeSet.SpanCondition.SIMPLE);
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(suffixStart==0) {
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(doNormalize) {
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    norm2.normalizeSecondAndAppend(first, prefix);
2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    norm2.append(first, prefix);
2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                StringBuilder middle=new StringBuilder(
2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        first.subSequence(suffixStart, first.length()));
2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(doNormalize) {
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    norm2.normalizeSecondAndAppend(middle, prefix);
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    norm2.append(middle, prefix);
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                first.delete(suffixStart, 0x7fffffff).append(middle);
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(prefixLimit<second.length()) {
2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            CharSequence rest=second.subSequence(prefixLimit, second.length());
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(doNormalize) {
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                normalize(rest, first, UnicodeSet.SpanCondition.NOT_CONTAINED);
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                first.append(rest);
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return first;
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private Normalizer2 norm2;
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private UnicodeSet set;
2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller};
291