]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/classes/core/src/com/ibm/icu/impl/Norm2AllModes.java
Added flags.
[Dictionary.git] / jars / icu4j-52_1 / main / classes / core / src / com / ibm / icu / impl / Norm2AllModes.java
1 /*
2 *******************************************************************************
3 *   Copyright (C) 2009-2011, International Business Machines
4 *   Corporation and others.  All Rights Reserved.
5 *******************************************************************************
6 */
7 package com.ibm.icu.impl;
8
9 import java.io.IOException;
10 import java.io.InputStream;
11
12 import com.ibm.icu.text.Normalizer;
13 import com.ibm.icu.text.Normalizer2;
14
15 public final class Norm2AllModes {
16     // Public API dispatch via Normalizer2 subclasses -------------------------- ***
17
18     // Normalizer2 implementation for the old UNORM_NONE.
19     public static final class NoopNormalizer2 extends Normalizer2 {
20         @Override
21         public StringBuilder normalize(CharSequence src, StringBuilder dest) {
22             if(dest!=src) {
23                 dest.setLength(0);
24                 return dest.append(src);
25             } else {
26                 throw new IllegalArgumentException();
27             }
28         }
29         @Override
30         public Appendable normalize(CharSequence src, Appendable dest) {
31             if(dest!=src) {
32                 try {
33                     return dest.append(src);
34                 } catch(IOException e) {
35                     throw new RuntimeException(e);  // Avoid declaring "throws IOException".
36                 }
37             } else {
38                 throw new IllegalArgumentException();
39             }
40         }
41         @Override
42         public StringBuilder normalizeSecondAndAppend(StringBuilder first, CharSequence second) {
43             if(first!=second) {
44                 return first.append(second);
45             } else {
46                 throw new IllegalArgumentException();
47             }
48         }
49         @Override
50         public StringBuilder append(StringBuilder first, CharSequence second) {
51             if(first!=second) {
52                 return first.append(second);
53             } else {
54                 throw new IllegalArgumentException();
55             }
56         }
57         @Override
58         public String getDecomposition(int c) {
59             return null;
60         }
61         // No need to override the default getRawDecomposition().
62         @Override
63         public boolean isNormalized(CharSequence s) { return true; }
64         @Override
65         public Normalizer.QuickCheckResult quickCheck(CharSequence s) { return Normalizer.YES; }
66         @Override
67         public int spanQuickCheckYes(CharSequence s) { return s.length(); }
68         @Override
69         public boolean hasBoundaryBefore(int c) { return true; }
70         @Override
71         public boolean hasBoundaryAfter(int c) { return true; }
72         @Override
73         public boolean isInert(int c) { return true; }
74     }
75
76     // Intermediate class:
77     // Has Normalizer2Impl and does boilerplate argument checking and setup.
78     public static abstract class Normalizer2WithImpl extends Normalizer2 {
79         public Normalizer2WithImpl(Normalizer2Impl ni) {
80             impl=ni;
81         }
82
83         // normalize
84         @Override
85         public StringBuilder normalize(CharSequence src, StringBuilder dest) {
86             if(dest==src) {
87                 throw new IllegalArgumentException();
88             }
89             dest.setLength(0);
90             normalize(src, new Normalizer2Impl.ReorderingBuffer(impl, dest, src.length()));
91             return dest;
92         }
93         @Override
94         public Appendable normalize(CharSequence src, Appendable dest) {
95             if(dest==src) {
96                 throw new IllegalArgumentException();
97             }
98             Normalizer2Impl.ReorderingBuffer buffer=
99                 new Normalizer2Impl.ReorderingBuffer(impl, dest, src.length());
100             normalize(src, buffer);
101             buffer.flush();
102             return dest;
103         }
104         protected abstract void normalize(CharSequence src, Normalizer2Impl.ReorderingBuffer buffer);
105
106         // normalize and append
107         @Override
108         public StringBuilder normalizeSecondAndAppend(StringBuilder first, CharSequence second) {
109             return normalizeSecondAndAppend(first, second, true);
110         }
111         @Override
112         public StringBuilder append(StringBuilder first, CharSequence second) {
113             return normalizeSecondAndAppend(first, second, false);
114         }
115         public StringBuilder normalizeSecondAndAppend(
116                 StringBuilder first, CharSequence second, boolean doNormalize) {
117             if(first==second) {
118                 throw new IllegalArgumentException();
119             }
120             normalizeAndAppend(
121                 second, doNormalize,
122                 new Normalizer2Impl.ReorderingBuffer(impl, first, first.length()+second.length()));
123             return first;
124         }
125         protected abstract void normalizeAndAppend(
126                 CharSequence src, boolean doNormalize, Normalizer2Impl.ReorderingBuffer buffer);
127
128         @Override
129         public String getDecomposition(int c) {
130             return impl.getDecomposition(c);
131         }
132         @Override
133         public String getRawDecomposition(int c) {
134             return impl.getRawDecomposition(c);
135         }
136         @Override
137         public int composePair(int a, int b) {
138             return impl.composePair(a, b);
139         }
140
141         @Override
142         public int getCombiningClass(int c) {
143             return impl.getCC(impl.getNorm16(c));
144         }
145
146         // quick checks
147         @Override
148         public boolean isNormalized(CharSequence s) {
149             return s.length()==spanQuickCheckYes(s);
150         }
151         @Override
152         public Normalizer.QuickCheckResult quickCheck(CharSequence s) {
153             return isNormalized(s) ? Normalizer.YES : Normalizer.NO;
154         }
155
156         public int getQuickCheck(int c) {
157             return 1;
158         }
159
160         public final Normalizer2Impl impl;
161     }
162
163     public static final class DecomposeNormalizer2 extends Normalizer2WithImpl {
164         public DecomposeNormalizer2(Normalizer2Impl ni) {
165             super(ni);
166         }
167
168         @Override
169         protected void normalize(CharSequence src, Normalizer2Impl.ReorderingBuffer buffer) {
170             impl.decompose(src, 0, src.length(), buffer);
171         }
172         @Override
173         protected void normalizeAndAppend(
174                 CharSequence src, boolean doNormalize, Normalizer2Impl.ReorderingBuffer buffer) {
175             impl.decomposeAndAppend(src, doNormalize, buffer);
176         }
177         @Override
178         public int spanQuickCheckYes(CharSequence s) {
179             return impl.decompose(s, 0, s.length(), null);
180         }
181         @Override
182         public int getQuickCheck(int c) {
183             return impl.isDecompYes(impl.getNorm16(c)) ? 1 : 0;
184         }
185         @Override
186         public boolean hasBoundaryBefore(int c) { return impl.hasDecompBoundary(c, true); }
187         @Override
188         public boolean hasBoundaryAfter(int c) { return impl.hasDecompBoundary(c, false); }
189         @Override
190         public boolean isInert(int c) { return impl.isDecompInert(c); }
191     }
192
193     public static final class ComposeNormalizer2 extends Normalizer2WithImpl {
194         public ComposeNormalizer2(Normalizer2Impl ni, boolean fcc) {
195             super(ni);
196             onlyContiguous=fcc;
197         }
198
199         @Override
200         protected void normalize(CharSequence src, Normalizer2Impl.ReorderingBuffer buffer) {
201             impl.compose(src, 0, src.length(), onlyContiguous, true, buffer);
202         }
203         @Override
204         protected void normalizeAndAppend(
205                 CharSequence src, boolean doNormalize, Normalizer2Impl.ReorderingBuffer buffer) {
206             impl.composeAndAppend(src, doNormalize, onlyContiguous, buffer);
207         }
208
209         @Override
210         public boolean isNormalized(CharSequence s) {
211             // 5: small destCapacity for substring normalization
212             return impl.compose(s, 0, s.length(),
213                                 onlyContiguous, false,
214                                 new Normalizer2Impl.ReorderingBuffer(impl, new StringBuilder(), 5));
215         }
216         @Override
217         public Normalizer.QuickCheckResult quickCheck(CharSequence s) {
218             int spanLengthAndMaybe=impl.composeQuickCheck(s, 0, s.length(), onlyContiguous, false);
219             if((spanLengthAndMaybe&1)!=0) {
220                 return Normalizer.MAYBE;
221             } else if((spanLengthAndMaybe>>>1)==s.length()) {
222                 return Normalizer.YES;
223             } else {
224                 return Normalizer.NO;
225             }
226         }
227         @Override
228         public int spanQuickCheckYes(CharSequence s) {
229             return impl.composeQuickCheck(s, 0, s.length(), onlyContiguous, true)>>>1;
230         }
231         @Override
232         public int getQuickCheck(int c) {
233             return impl.getCompQuickCheck(impl.getNorm16(c));
234         }
235         @Override
236         public boolean hasBoundaryBefore(int c) { return impl.hasCompBoundaryBefore(c); }
237         @Override
238         public boolean hasBoundaryAfter(int c) {
239             return impl.hasCompBoundaryAfter(c, onlyContiguous, false);
240         }
241         @Override
242         public boolean isInert(int c) {
243             return impl.hasCompBoundaryAfter(c, onlyContiguous, true);
244         }
245
246         private final boolean onlyContiguous;
247     }
248
249     public static final class FCDNormalizer2 extends Normalizer2WithImpl {
250         public FCDNormalizer2(Normalizer2Impl ni) {
251             super(ni);
252         }
253
254         @Override
255         protected void normalize(CharSequence src, Normalizer2Impl.ReorderingBuffer buffer) {
256             impl.makeFCD(src, 0, src.length(), buffer);
257         }
258         @Override
259         protected void normalizeAndAppend(
260                 CharSequence src, boolean doNormalize, Normalizer2Impl.ReorderingBuffer buffer) {
261             impl.makeFCDAndAppend(src, doNormalize, buffer);
262         }
263         @Override
264         public int spanQuickCheckYes(CharSequence s) {
265             return impl.makeFCD(s, 0, s.length(), null);
266         }
267         @Override
268         public int getQuickCheck(int c) {
269             return impl.isDecompYes(impl.getNorm16(c)) ? 1 : 0;
270         }
271         @Override
272         public boolean hasBoundaryBefore(int c) { return impl.hasFCDBoundaryBefore(c); }
273         @Override
274         public boolean hasBoundaryAfter(int c) { return impl.hasFCDBoundaryAfter(c); }
275         @Override
276         public boolean isInert(int c) { return impl.isFCDInert(c); }
277     }
278
279     // instance cache ---------------------------------------------------------- ***
280
281     private Norm2AllModes(Normalizer2Impl ni) {
282         impl=ni;
283         comp=new ComposeNormalizer2(ni, false);
284         decomp=new DecomposeNormalizer2(ni);
285         fcd=new FCDNormalizer2(ni);
286         fcc=new ComposeNormalizer2(ni, true);
287     }
288
289     public final Normalizer2Impl impl;
290     public final ComposeNormalizer2 comp;
291     public final DecomposeNormalizer2 decomp;
292     public final FCDNormalizer2 fcd;
293     public final ComposeNormalizer2 fcc;
294
295     private static Norm2AllModes getInstanceFromSingleton(Norm2AllModesSingleton singleton) {
296         if(singleton.exception!=null) {
297             throw singleton.exception;
298         }
299         return singleton.allModes;
300     }
301     public static Norm2AllModes getNFCInstance() {
302         return getInstanceFromSingleton(NFCSingleton.INSTANCE);
303     }
304     public static Norm2AllModes getNFKCInstance() {
305         return getInstanceFromSingleton(NFKCSingleton.INSTANCE);
306     }
307     public static Norm2AllModes getNFKC_CFInstance() {
308         return getInstanceFromSingleton(NFKC_CFSingleton.INSTANCE);
309     }
310     // For use in properties APIs.
311     public static Normalizer2WithImpl getN2WithImpl(int index) {
312         switch(index) {
313         case 0: return getNFCInstance().decomp;  // NFD
314         case 1: return getNFKCInstance().decomp; // NFKD
315         case 2: return getNFCInstance().comp;    // NFC
316         case 3: return getNFKCInstance().comp;   // NFKC
317         default: return null;
318         }
319     }
320     public static Norm2AllModes getInstance(InputStream data, String name) {
321         if(data==null) {
322             Norm2AllModesSingleton singleton;
323             if(name.equals("nfc")) {
324                 singleton=NFCSingleton.INSTANCE;
325             } else if(name.equals("nfkc")) {
326                 singleton=NFKCSingleton.INSTANCE;
327             } else if(name.equals("nfkc_cf")) {
328                 singleton=NFKC_CFSingleton.INSTANCE;
329             } else {
330                 singleton=null;
331             }
332             if(singleton!=null) {
333                 if(singleton.exception!=null) {
334                     throw singleton.exception;
335                 }
336                 return singleton.allModes;
337             }
338         }
339         return cache.getInstance(name, data);
340     }
341     private static CacheBase<String, Norm2AllModes, InputStream> cache =
342         new SoftCache<String, Norm2AllModes, InputStream>() {
343             protected Norm2AllModes createInstance(String key, InputStream data) {
344                 Normalizer2Impl impl;
345                 if(data==null) {
346                     impl=new Normalizer2Impl().load(ICUResourceBundle.ICU_BUNDLE+"/"+key+".nrm");
347                 } else {
348                     impl=new Normalizer2Impl().load(data);
349                 }
350                 return new Norm2AllModes(impl);
351             }
352         };
353
354     public static final NoopNormalizer2 NOOP_NORMALIZER2=new NoopNormalizer2();
355     /**
356      * Gets the FCD normalizer, with the FCD data initialized.
357      * @return FCD normalizer
358      */
359     public static Normalizer2 getFCDNormalizer2() {
360         return getNFCInstance().fcd;
361     }
362
363     private static final class Norm2AllModesSingleton {
364         private Norm2AllModesSingleton(String name) {
365             try {
366                 Normalizer2Impl impl=new Normalizer2Impl().load(
367                         ICUResourceBundle.ICU_BUNDLE+"/"+name+".nrm");
368                 allModes=new Norm2AllModes(impl);
369             } catch(RuntimeException e) {
370                 exception=e;
371             }
372         }
373
374         private Norm2AllModes allModes;
375         private RuntimeException exception;
376     }
377     private static final class NFCSingleton {
378         private static final Norm2AllModesSingleton INSTANCE=new Norm2AllModesSingleton("nfc");
379     }
380     private static final class NFKCSingleton {
381         private static final Norm2AllModesSingleton INSTANCE=new Norm2AllModesSingleton("nfkc");
382     }
383     private static final class NFKC_CFSingleton {
384         private static final Norm2AllModesSingleton INSTANCE=new Norm2AllModesSingleton("nfkc_cf");
385     }
386 }