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) 2001-2014, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 ********************************************************************** 9 * Date Name Description 10 * 06/08/01 aliu Creation. 11 ********************************************************************** 12 */ 13 14 package ohos.global.icu.text; 15 import java.util.HashMap; 16 import java.util.Map; 17 18 import ohos.global.icu.impl.Norm2AllModes; 19 import ohos.global.icu.impl.Normalizer2Impl; 20 21 /** 22 * @author Alan Liu, Markus Scherer 23 */ 24 final class NormalizationTransliterator extends Transliterator { 25 private final Normalizer2 norm2; 26 27 /** 28 * System registration hook. 29 */ register()30 static void register() { 31 Transliterator.registerFactory("Any-NFC", new Transliterator.Factory() { 32 @Override 33 public Transliterator getInstance(String ID) { 34 return new NormalizationTransliterator("NFC", Normalizer2.getNFCInstance()); 35 } 36 }); 37 Transliterator.registerFactory("Any-NFD", new Transliterator.Factory() { 38 @Override 39 public Transliterator getInstance(String ID) { 40 return new NormalizationTransliterator("NFD", Normalizer2.getNFDInstance()); 41 } 42 }); 43 Transliterator.registerFactory("Any-NFKC", new Transliterator.Factory() { 44 @Override 45 public Transliterator getInstance(String ID) { 46 return new NormalizationTransliterator("NFKC", Normalizer2.getNFKCInstance()); 47 } 48 }); 49 Transliterator.registerFactory("Any-NFKD", new Transliterator.Factory() { 50 @Override 51 public Transliterator getInstance(String ID) { 52 return new NormalizationTransliterator("NFKD", Normalizer2.getNFKDInstance()); 53 } 54 }); 55 Transliterator.registerFactory("Any-FCD", new Transliterator.Factory() { 56 @Override 57 public Transliterator getInstance(String ID) { 58 return new NormalizationTransliterator("FCD", Norm2AllModes.getFCDNormalizer2()); 59 } 60 }); 61 Transliterator.registerFactory("Any-FCC", new Transliterator.Factory() { 62 @Override 63 public Transliterator getInstance(String ID) { 64 return new NormalizationTransliterator("FCC", Norm2AllModes.getNFCInstance().fcc); 65 } 66 }); 67 Transliterator.registerSpecialInverse("NFC", "NFD", true); 68 Transliterator.registerSpecialInverse("NFKC", "NFKD", true); 69 Transliterator.registerSpecialInverse("FCC", "NFD", false); 70 Transliterator.registerSpecialInverse("FCD", "FCD", false); 71 } 72 73 /** 74 * Constructs a transliterator. 75 */ NormalizationTransliterator(String id, Normalizer2 n2)76 private NormalizationTransliterator(String id, Normalizer2 n2) { 77 super(id, null); 78 norm2 = n2; 79 } 80 81 /** 82 * Implements {@link Transliterator#handleTransliterate}. 83 */ 84 @Override handleTransliterate(Replaceable text, Position offsets, boolean isIncremental)85 protected void handleTransliterate(Replaceable text, 86 Position offsets, boolean isIncremental) { 87 // start and limit of the input range 88 int start = offsets.start; 89 int limit = offsets.limit; 90 if(start >= limit) { 91 return; 92 } 93 94 /* 95 * Normalize as short chunks at a time as possible even in 96 * bulk mode, so that styled text is minimally disrupted. 97 * In incremental mode, a chunk that ends with offsets.limit 98 * must not be normalized. 99 * 100 * If it was known that the input text is not styled, then 101 * a bulk mode normalization could be used. 102 * (For details, see the comment in the C++ version.) 103 */ 104 StringBuilder segment = new StringBuilder(); 105 StringBuilder normalized = new StringBuilder(); 106 int c = text.char32At(start); 107 do { 108 int prev = start; 109 // Skip at least one character so we make progress. 110 // c holds the character at start. 111 segment.setLength(0); 112 do { 113 segment.appendCodePoint(c); 114 start += Character.charCount(c); 115 } while(start < limit && !norm2.hasBoundaryBefore(c = text.char32At(start))); 116 if(start == limit && isIncremental && !norm2.hasBoundaryAfter(c)) { 117 // stop in incremental mode when we reach the input limit 118 // in case there are additional characters that could change the 119 // normalization result 120 start=prev; 121 break; 122 } 123 norm2.normalize(segment, normalized); 124 if(!Normalizer2Impl.UTF16Plus.equal(segment, normalized)) { 125 // replace the input chunk with its normalized form 126 text.replace(prev, start, normalized.toString()); 127 128 // update all necessary indexes accordingly 129 int delta = normalized.length() - (start - prev); 130 start += delta; 131 limit += delta; 132 } 133 } while(start < limit); 134 135 offsets.start = start; 136 offsets.contextLimit += limit - offsets.limit; 137 offsets.limit = limit; 138 } 139 140 static final Map<Normalizer2, SourceTargetUtility> SOURCE_CACHE = new HashMap<Normalizer2, SourceTargetUtility>(); 141 142 // TODO Get rid of this if Normalizer2 becomes a Transform 143 static class NormalizingTransform implements Transform<String,String> { 144 final Normalizer2 norm2; NormalizingTransform(Normalizer2 norm2)145 public NormalizingTransform(Normalizer2 norm2) { 146 this.norm2 = norm2; 147 } 148 @Override transform(String source)149 public String transform(String source) { 150 return norm2.normalize(source); 151 } 152 } 153 154 /* (non-Javadoc) 155 * @see ohos.global.icu.text.Transliterator#addSourceTargetSet(ohos.global.icu.text.UnicodeSet, ohos.global.icu.text.UnicodeSet, ohos.global.icu.text.UnicodeSet) 156 */ 157 @Override addSourceTargetSet(UnicodeSet inputFilter, UnicodeSet sourceSet, UnicodeSet targetSet)158 public void addSourceTargetSet(UnicodeSet inputFilter, UnicodeSet sourceSet, UnicodeSet targetSet) { 159 SourceTargetUtility cache; 160 synchronized (SOURCE_CACHE) { 161 //String id = getID(); 162 cache = SOURCE_CACHE.get(norm2); 163 if (cache == null) { 164 cache = new SourceTargetUtility(new NormalizingTransform(norm2), norm2); 165 SOURCE_CACHE.put(norm2, cache); 166 } 167 } 168 cache.addSourceTargetSet(this, inputFilter, sourceSet, targetSet); 169 } 170 } 171