1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2016 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4/*
5 *******************************************************************************
6 * Copyright (C) 1996-2011, International Business Machines Corporation and    *
7 * others. All Rights Reserved.                                                *
8 *******************************************************************************
9 */
10package android.icu.text;
11
12import android.icu.impl.UCaseProps;
13import android.icu.lang.UCharacter;
14import android.icu.util.ULocale;
15
16/**
17 * A transliterator that performs locale-sensitive toLower()
18 * case mapping.
19 */
20class LowercaseTransliterator extends Transliterator{
21
22    /**
23     * Package accessible ID.
24     */
25    static final String _ID = "Any-Lower";
26
27    // TODO: Add variants for tr/az, lt, default = default locale: ICU ticket #12720
28
29    /**
30     * System registration hook.
31     */
32    static void register() {
33        Transliterator.registerFactory(_ID, new Transliterator.Factory() {
34            @Override
35            public Transliterator getInstance(String ID) {
36                return new LowercaseTransliterator(ULocale.US);
37            }
38        });
39
40        Transliterator.registerSpecialInverse("Lower", "Upper", true);
41    }
42
43    private final ULocale locale;
44
45    private final UCaseProps csp;
46    private ReplaceableContextIterator iter;
47    private StringBuilder result;
48    private int caseLocale;
49
50    /**
51     * Constructs a transliterator.
52     */
53
54    public LowercaseTransliterator(ULocale loc) {
55        super(_ID, null);
56        locale = loc;
57        csp=UCaseProps.INSTANCE;
58        iter=new ReplaceableContextIterator();
59        result = new StringBuilder();
60        caseLocale = UCaseProps.getCaseLocale(locale);
61    }
62
63    /**
64     * Implements {@link Transliterator#handleTransliterate}.
65     */
66    @Override
67    protected synchronized void handleTransliterate(Replaceable text,
68                                       Position offsets, boolean isIncremental) {
69        if(csp==null) {
70            return;
71        }
72
73        if(offsets.start >= offsets.limit) {
74            return;
75        }
76
77        iter.setText(text);
78        result.setLength(0);
79        int c, delta;
80
81        // Walk through original string
82        // If there is a case change, modify corresponding position in replaceable
83
84        iter.setIndex(offsets.start);
85        iter.setLimit(offsets.limit);
86        iter.setContextLimits(offsets.contextStart, offsets.contextLimit);
87        while((c=iter.nextCaseMapCP())>=0) {
88            c=csp.toFullLower(c, iter, result, caseLocale);
89
90            if(iter.didReachLimit() && isIncremental) {
91                // the case mapping function tried to look beyond the context limit
92                // wait for more input
93                offsets.start=iter.getCaseMapCPStart();
94                return;
95            }
96
97            /* decode the result */
98            if(c<0) {
99                /* c mapped to itself, no change */
100                continue;
101            } else if(c<=UCaseProps.MAX_STRING_LENGTH) {
102                /* replace by the mapping string */
103                delta=iter.replace(result.toString());
104                result.setLength(0);
105            } else {
106                /* replace by single-code point mapping */
107                delta=iter.replace(UTF16.valueOf(c));
108            }
109
110            if(delta!=0) {
111                offsets.limit += delta;
112                offsets.contextLimit += delta;
113            }
114        }
115        offsets.start = offsets.limit;
116    }
117
118    // NOTE: normally this would be static, but because the results vary by locale....
119    SourceTargetUtility sourceTargetUtility = null;
120
121    /* (non-Javadoc)
122     * @see android.icu.text.Transliterator#addSourceTargetSet(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet, android.icu.text.UnicodeSet)
123     */
124    @Override
125    public void addSourceTargetSet(UnicodeSet inputFilter, UnicodeSet sourceSet, UnicodeSet targetSet) {
126        synchronized (this) {
127            if (sourceTargetUtility == null) {
128                sourceTargetUtility = new SourceTargetUtility(new Transform<String,String>() {
129                    @Override
130                    public String transform(String source) {
131                        return UCharacter.toLowerCase(locale, source);
132                    }
133                });
134            }
135        }
136        sourceTargetUtility.addSourceTargetSet(this, inputFilter, sourceSet, targetSet);
137    }
138}
139