OLD | NEW |
1 /* | 1 /* |
2 ******************************************************************************* | 2 ******************************************************************************* |
3 * | 3 * |
4 * Copyright (C) 2009-2013, International Business Machines | 4 * Copyright (C) 2009-2014, International Business Machines |
5 * Corporation and others. All Rights Reserved. | 5 * Corporation and others. All Rights Reserved. |
6 * | 6 * |
7 ******************************************************************************* | 7 ******************************************************************************* |
8 * file name: normalizer2.cpp | 8 * file name: normalizer2.cpp |
9 * encoding: US-ASCII | 9 * encoding: US-ASCII |
10 * tab size: 8 (not used) | 10 * tab size: 8 (not used) |
11 * indentation:4 | 11 * indentation:4 |
12 * | 12 * |
13 * created on: 2009nov22 | 13 * created on: 2009nov22 |
14 * created by: Markus W. Scherer | 14 * created by: Markus W. Scherer |
15 */ | 15 */ |
16 | 16 |
17 #include "unicode/utypes.h" | 17 #include "unicode/utypes.h" |
18 | 18 |
19 #if !UCONFIG_NO_NORMALIZATION | 19 #if !UCONFIG_NO_NORMALIZATION |
20 | 20 |
21 #include "unicode/localpointer.h" | |
22 #include "unicode/normalizer2.h" | 21 #include "unicode/normalizer2.h" |
23 #include "unicode/unistr.h" | 22 #include "unicode/unistr.h" |
24 #include "unicode/unorm.h" | 23 #include "unicode/unorm.h" |
25 #include "cpputils.h" | |
26 #include "cstring.h" | 24 #include "cstring.h" |
27 #include "mutex.h" | 25 #include "mutex.h" |
| 26 #include "norm2allmodes.h" |
28 #include "normalizer2impl.h" | 27 #include "normalizer2impl.h" |
29 #include "uassert.h" | 28 #include "uassert.h" |
30 #include "ucln_cmn.h" | 29 #include "ucln_cmn.h" |
31 #include "uhash.h" | 30 |
| 31 using icu::Normalizer2Impl; |
| 32 |
| 33 // NFC/NFD data machine-generated by gennorm2 --csource |
| 34 #include "norm2_nfc_data.h" |
32 | 35 |
33 U_NAMESPACE_BEGIN | 36 U_NAMESPACE_BEGIN |
34 | 37 |
35 // Public API dispatch via Normalizer2 subclasses -------------------------- *** | 38 // Public API dispatch via Normalizer2 subclasses -------------------------- *** |
36 | 39 |
37 Normalizer2::~Normalizer2() {} | 40 Normalizer2::~Normalizer2() {} |
38 | 41 |
39 UBool | 42 UBool |
40 Normalizer2::getRawDecomposition(UChar32, UnicodeString &) const { | 43 Normalizer2::getRawDecomposition(UChar32, UnicodeString &) const { |
41 return FALSE; | 44 return FALSE; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 spanQuickCheckYes(const UnicodeString &s, UErrorCode &) const { | 114 spanQuickCheckYes(const UnicodeString &s, UErrorCode &) const { |
112 return s.length(); | 115 return s.length(); |
113 } | 116 } |
114 virtual UBool hasBoundaryBefore(UChar32) const { return TRUE; } | 117 virtual UBool hasBoundaryBefore(UChar32) const { return TRUE; } |
115 virtual UBool hasBoundaryAfter(UChar32) const { return TRUE; } | 118 virtual UBool hasBoundaryAfter(UChar32) const { return TRUE; } |
116 virtual UBool isInert(UChar32) const { return TRUE; } | 119 virtual UBool isInert(UChar32) const { return TRUE; } |
117 }; | 120 }; |
118 | 121 |
119 NoopNormalizer2::~NoopNormalizer2() {} | 122 NoopNormalizer2::~NoopNormalizer2() {} |
120 | 123 |
121 // Intermediate class: | |
122 // Has Normalizer2Impl and does boilerplate argument checking and setup. | |
123 class Normalizer2WithImpl : public Normalizer2 { | |
124 public: | |
125 Normalizer2WithImpl(const Normalizer2Impl &ni) : impl(ni) {} | |
126 virtual ~Normalizer2WithImpl(); | |
127 | |
128 // normalize | |
129 virtual UnicodeString & | |
130 normalize(const UnicodeString &src, | |
131 UnicodeString &dest, | |
132 UErrorCode &errorCode) const { | |
133 if(U_FAILURE(errorCode)) { | |
134 dest.setToBogus(); | |
135 return dest; | |
136 } | |
137 const UChar *sArray=src.getBuffer(); | |
138 if(&dest==&src || sArray==NULL) { | |
139 errorCode=U_ILLEGAL_ARGUMENT_ERROR; | |
140 dest.setToBogus(); | |
141 return dest; | |
142 } | |
143 dest.remove(); | |
144 ReorderingBuffer buffer(impl, dest); | |
145 if(buffer.init(src.length(), errorCode)) { | |
146 normalize(sArray, sArray+src.length(), buffer, errorCode); | |
147 } | |
148 return dest; | |
149 } | |
150 virtual void | |
151 normalize(const UChar *src, const UChar *limit, | |
152 ReorderingBuffer &buffer, UErrorCode &errorCode) const = 0; | |
153 | |
154 // normalize and append | |
155 virtual UnicodeString & | |
156 normalizeSecondAndAppend(UnicodeString &first, | |
157 const UnicodeString &second, | |
158 UErrorCode &errorCode) const { | |
159 return normalizeSecondAndAppend(first, second, TRUE, errorCode); | |
160 } | |
161 virtual UnicodeString & | |
162 append(UnicodeString &first, | |
163 const UnicodeString &second, | |
164 UErrorCode &errorCode) const { | |
165 return normalizeSecondAndAppend(first, second, FALSE, errorCode); | |
166 } | |
167 UnicodeString & | |
168 normalizeSecondAndAppend(UnicodeString &first, | |
169 const UnicodeString &second, | |
170 UBool doNormalize, | |
171 UErrorCode &errorCode) const { | |
172 uprv_checkCanGetBuffer(first, errorCode); | |
173 if(U_FAILURE(errorCode)) { | |
174 return first; | |
175 } | |
176 const UChar *secondArray=second.getBuffer(); | |
177 if(&first==&second || secondArray==NULL) { | |
178 errorCode=U_ILLEGAL_ARGUMENT_ERROR; | |
179 return first; | |
180 } | |
181 int32_t firstLength=first.length(); | |
182 UnicodeString safeMiddle; | |
183 { | |
184 ReorderingBuffer buffer(impl, first); | |
185 if(buffer.init(firstLength+second.length(), errorCode)) { | |
186 normalizeAndAppend(secondArray, secondArray+second.length(), doN
ormalize, | |
187 safeMiddle, buffer, errorCode); | |
188 } | |
189 } // The ReorderingBuffer destructor finalizes the first string. | |
190 if(U_FAILURE(errorCode)) { | |
191 // Restore the modified suffix of the first string. | |
192 first.replace(firstLength-safeMiddle.length(), 0x7fffffff, safeMiddl
e); | |
193 } | |
194 return first; | |
195 } | |
196 virtual void | |
197 normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, | |
198 UnicodeString &safeMiddle, | |
199 ReorderingBuffer &buffer, UErrorCode &errorCode) const =
0; | |
200 virtual UBool | |
201 getDecomposition(UChar32 c, UnicodeString &decomposition) const { | |
202 UChar buffer[4]; | |
203 int32_t length; | |
204 const UChar *d=impl.getDecomposition(c, buffer, length); | |
205 if(d==NULL) { | |
206 return FALSE; | |
207 } | |
208 if(d==buffer) { | |
209 decomposition.setTo(buffer, length); // copy the string (Jamos from
Hangul syllable c) | |
210 } else { | |
211 decomposition.setTo(FALSE, d, length); // read-only alias | |
212 } | |
213 return TRUE; | |
214 } | |
215 virtual UBool | |
216 getRawDecomposition(UChar32 c, UnicodeString &decomposition) const { | |
217 UChar buffer[30]; | |
218 int32_t length; | |
219 const UChar *d=impl.getRawDecomposition(c, buffer, length); | |
220 if(d==NULL) { | |
221 return FALSE; | |
222 } | |
223 if(d==buffer) { | |
224 decomposition.setTo(buffer, length); // copy the string (algorithmi
c decomposition) | |
225 } else { | |
226 decomposition.setTo(FALSE, d, length); // read-only alias | |
227 } | |
228 return TRUE; | |
229 } | |
230 virtual UChar32 | |
231 composePair(UChar32 a, UChar32 b) const { | |
232 return impl.composePair(a, b); | |
233 } | |
234 | |
235 virtual uint8_t | |
236 getCombiningClass(UChar32 c) const { | |
237 return impl.getCC(impl.getNorm16(c)); | |
238 } | |
239 | |
240 // quick checks | |
241 virtual UBool | |
242 isNormalized(const UnicodeString &s, UErrorCode &errorCode) const { | |
243 if(U_FAILURE(errorCode)) { | |
244 return FALSE; | |
245 } | |
246 const UChar *sArray=s.getBuffer(); | |
247 if(sArray==NULL) { | |
248 errorCode=U_ILLEGAL_ARGUMENT_ERROR; | |
249 return FALSE; | |
250 } | |
251 const UChar *sLimit=sArray+s.length(); | |
252 return sLimit==spanQuickCheckYes(sArray, sLimit, errorCode); | |
253 } | |
254 virtual UNormalizationCheckResult | |
255 quickCheck(const UnicodeString &s, UErrorCode &errorCode) const { | |
256 return Normalizer2WithImpl::isNormalized(s, errorCode) ? UNORM_YES : UNO
RM_NO; | |
257 } | |
258 virtual int32_t | |
259 spanQuickCheckYes(const UnicodeString &s, UErrorCode &errorCode) const { | |
260 if(U_FAILURE(errorCode)) { | |
261 return 0; | |
262 } | |
263 const UChar *sArray=s.getBuffer(); | |
264 if(sArray==NULL) { | |
265 errorCode=U_ILLEGAL_ARGUMENT_ERROR; | |
266 return 0; | |
267 } | |
268 return (int32_t)(spanQuickCheckYes(sArray, sArray+s.length(), errorCode)
-sArray); | |
269 } | |
270 virtual const UChar * | |
271 spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCod
e) const = 0; | |
272 | |
273 virtual UNormalizationCheckResult getQuickCheck(UChar32) const { | |
274 return UNORM_YES; | |
275 } | |
276 | |
277 const Normalizer2Impl &impl; | |
278 }; | |
279 | |
280 Normalizer2WithImpl::~Normalizer2WithImpl() {} | 124 Normalizer2WithImpl::~Normalizer2WithImpl() {} |
281 | 125 |
282 class DecomposeNormalizer2 : public Normalizer2WithImpl { | |
283 public: | |
284 DecomposeNormalizer2(const Normalizer2Impl &ni) : Normalizer2WithImpl(ni) {} | |
285 virtual ~DecomposeNormalizer2(); | |
286 | |
287 private: | |
288 virtual void | |
289 normalize(const UChar *src, const UChar *limit, | |
290 ReorderingBuffer &buffer, UErrorCode &errorCode) const { | |
291 impl.decompose(src, limit, &buffer, errorCode); | |
292 } | |
293 using Normalizer2WithImpl::normalize; // Avoid warning about hiding base cl
ass function. | |
294 virtual void | |
295 normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, | |
296 UnicodeString &safeMiddle, | |
297 ReorderingBuffer &buffer, UErrorCode &errorCode) const { | |
298 impl.decomposeAndAppend(src, limit, doNormalize, safeMiddle, buffer, err
orCode); | |
299 } | |
300 virtual const UChar * | |
301 spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCod
e) const { | |
302 return impl.decompose(src, limit, NULL, errorCode); | |
303 } | |
304 using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding
base class function. | |
305 virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const { | |
306 return impl.isDecompYes(impl.getNorm16(c)) ? UNORM_YES : UNORM_NO; | |
307 } | |
308 virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasDecompBoun
dary(c, TRUE); } | |
309 virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasDecompBound
ary(c, FALSE); } | |
310 virtual UBool isInert(UChar32 c) const { return impl.isDecompInert(c); } | |
311 }; | |
312 | |
313 DecomposeNormalizer2::~DecomposeNormalizer2() {} | 126 DecomposeNormalizer2::~DecomposeNormalizer2() {} |
314 | 127 |
315 class ComposeNormalizer2 : public Normalizer2WithImpl { | |
316 public: | |
317 ComposeNormalizer2(const Normalizer2Impl &ni, UBool fcc) : | |
318 Normalizer2WithImpl(ni), onlyContiguous(fcc) {} | |
319 virtual ~ComposeNormalizer2(); | |
320 | |
321 private: | |
322 virtual void | |
323 normalize(const UChar *src, const UChar *limit, | |
324 ReorderingBuffer &buffer, UErrorCode &errorCode) const { | |
325 impl.compose(src, limit, onlyContiguous, TRUE, buffer, errorCode); | |
326 } | |
327 using Normalizer2WithImpl::normalize; // Avoid warning about hiding base cl
ass function. | |
328 virtual void | |
329 normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, | |
330 UnicodeString &safeMiddle, | |
331 ReorderingBuffer &buffer, UErrorCode &errorCode) const { | |
332 impl.composeAndAppend(src, limit, doNormalize, onlyContiguous, safeMiddl
e, buffer, errorCode); | |
333 } | |
334 | |
335 virtual UBool | |
336 isNormalized(const UnicodeString &s, UErrorCode &errorCode) const { | |
337 if(U_FAILURE(errorCode)) { | |
338 return FALSE; | |
339 } | |
340 const UChar *sArray=s.getBuffer(); | |
341 if(sArray==NULL) { | |
342 errorCode=U_ILLEGAL_ARGUMENT_ERROR; | |
343 return FALSE; | |
344 } | |
345 UnicodeString temp; | |
346 ReorderingBuffer buffer(impl, temp); | |
347 if(!buffer.init(5, errorCode)) { // small destCapacity for substring no
rmalization | |
348 return FALSE; | |
349 } | |
350 return impl.compose(sArray, sArray+s.length(), onlyContiguous, FALSE, bu
ffer, errorCode); | |
351 } | |
352 virtual UNormalizationCheckResult | |
353 quickCheck(const UnicodeString &s, UErrorCode &errorCode) const { | |
354 if(U_FAILURE(errorCode)) { | |
355 return UNORM_MAYBE; | |
356 } | |
357 const UChar *sArray=s.getBuffer(); | |
358 if(sArray==NULL) { | |
359 errorCode=U_ILLEGAL_ARGUMENT_ERROR; | |
360 return UNORM_MAYBE; | |
361 } | |
362 UNormalizationCheckResult qcResult=UNORM_YES; | |
363 impl.composeQuickCheck(sArray, sArray+s.length(), onlyContiguous, &qcRes
ult); | |
364 return qcResult; | |
365 } | |
366 virtual const UChar * | |
367 spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &) const
{ | |
368 return impl.composeQuickCheck(src, limit, onlyContiguous, NULL); | |
369 } | |
370 using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding
base class function. | |
371 virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const { | |
372 return impl.getCompQuickCheck(impl.getNorm16(c)); | |
373 } | |
374 virtual UBool hasBoundaryBefore(UChar32 c) const { | |
375 return impl.hasCompBoundaryBefore(c); | |
376 } | |
377 virtual UBool hasBoundaryAfter(UChar32 c) const { | |
378 return impl.hasCompBoundaryAfter(c, onlyContiguous, FALSE); | |
379 } | |
380 virtual UBool isInert(UChar32 c) const { | |
381 return impl.hasCompBoundaryAfter(c, onlyContiguous, TRUE); | |
382 } | |
383 | |
384 const UBool onlyContiguous; | |
385 }; | |
386 | |
387 ComposeNormalizer2::~ComposeNormalizer2() {} | 128 ComposeNormalizer2::~ComposeNormalizer2() {} |
388 | 129 |
389 class FCDNormalizer2 : public Normalizer2WithImpl { | |
390 public: | |
391 FCDNormalizer2(const Normalizer2Impl &ni) : Normalizer2WithImpl(ni) {} | |
392 virtual ~FCDNormalizer2(); | |
393 | |
394 private: | |
395 virtual void | |
396 normalize(const UChar *src, const UChar *limit, | |
397 ReorderingBuffer &buffer, UErrorCode &errorCode) const { | |
398 impl.makeFCD(src, limit, &buffer, errorCode); | |
399 } | |
400 using Normalizer2WithImpl::normalize; // Avoid warning about hiding base cl
ass function. | |
401 virtual void | |
402 normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, | |
403 UnicodeString &safeMiddle, | |
404 ReorderingBuffer &buffer, UErrorCode &errorCode) const { | |
405 impl.makeFCDAndAppend(src, limit, doNormalize, safeMiddle, buffer, error
Code); | |
406 } | |
407 virtual const UChar * | |
408 spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCod
e) const { | |
409 return impl.makeFCD(src, limit, NULL, errorCode); | |
410 } | |
411 using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding
base class function. | |
412 virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasFCDBoundar
yBefore(c); } | |
413 virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasFCDBoundary
After(c); } | |
414 virtual UBool isInert(UChar32 c) const { return impl.isFCDInert(c); } | |
415 }; | |
416 | |
417 FCDNormalizer2::~FCDNormalizer2() {} | 130 FCDNormalizer2::~FCDNormalizer2() {} |
418 | 131 |
419 // instance cache ---------------------------------------------------------- *** | 132 // instance cache ---------------------------------------------------------- *** |
420 | 133 |
421 struct Norm2AllModes : public UMemory { | 134 Norm2AllModes::~Norm2AllModes() { |
422 static Norm2AllModes *createInstance(const char *packageName, | 135 delete impl; |
423 const char *name, | 136 } |
424 UErrorCode &errorCode); | |
425 Norm2AllModes() : comp(impl, FALSE), decomp(impl), fcd(impl), fcc(impl, TRUE
) {} | |
426 | |
427 Normalizer2Impl impl; | |
428 ComposeNormalizer2 comp; | |
429 DecomposeNormalizer2 decomp; | |
430 FCDNormalizer2 fcd; | |
431 ComposeNormalizer2 fcc; | |
432 }; | |
433 | 137 |
434 Norm2AllModes * | 138 Norm2AllModes * |
435 Norm2AllModes::createInstance(const char *packageName, | 139 Norm2AllModes::createInstance(Normalizer2Impl *impl, UErrorCode &errorCode) { |
436 const char *name, | 140 if(U_FAILURE(errorCode)) { |
437 UErrorCode &errorCode) { | 141 delete impl; |
| 142 return NULL; |
| 143 } |
| 144 Norm2AllModes *allModes=new Norm2AllModes(impl); |
| 145 if(allModes==NULL) { |
| 146 errorCode=U_MEMORY_ALLOCATION_ERROR; |
| 147 delete impl; |
| 148 return NULL; |
| 149 } |
| 150 return allModes; |
| 151 } |
| 152 |
| 153 Norm2AllModes * |
| 154 Norm2AllModes::createNFCInstance(UErrorCode &errorCode) { |
438 if(U_FAILURE(errorCode)) { | 155 if(U_FAILURE(errorCode)) { |
439 return NULL; | 156 return NULL; |
440 } | 157 } |
441 LocalPointer<Norm2AllModes> allModes(new Norm2AllModes); | 158 Normalizer2Impl *impl=new Normalizer2Impl; |
442 if(allModes.isNull()) { | 159 if(impl==NULL) { |
443 errorCode=U_MEMORY_ALLOCATION_ERROR; | 160 errorCode=U_MEMORY_ALLOCATION_ERROR; |
444 return NULL; | 161 return NULL; |
445 } | 162 } |
446 allModes->impl.load(packageName, name, errorCode); | 163 impl->init(norm2_nfc_data_indexes, &norm2_nfc_data_trie, |
447 return U_SUCCESS(errorCode) ? allModes.orphan() : NULL; | 164 norm2_nfc_data_extraData, norm2_nfc_data_smallFCD); |
| 165 return createInstance(impl, errorCode); |
448 } | 166 } |
449 | 167 |
450 U_CDECL_BEGIN | 168 U_CDECL_BEGIN |
451 static UBool U_CALLCONV uprv_normalizer2_cleanup(); | 169 static UBool U_CALLCONV uprv_normalizer2_cleanup(); |
452 U_CDECL_END | 170 U_CDECL_END |
453 | 171 |
454 | |
455 static Norm2AllModes *nfcSingleton; | 172 static Norm2AllModes *nfcSingleton; |
456 static Norm2AllModes *nfkcSingleton; | |
457 static Norm2AllModes *nfkc_cfSingleton; | |
458 static Normalizer2 *noopSingleton; | 173 static Normalizer2 *noopSingleton; |
459 static UHashtable *cache=NULL; | |
460 | 174 |
461 static icu::UInitOnce nfcInitOnce = U_INITONCE_INITIALIZER; | 175 static icu::UInitOnce nfcInitOnce = U_INITONCE_INITIALIZER; |
462 static icu::UInitOnce nfkcInitOnce = U_INITONCE_INITIALIZER; | |
463 static icu::UInitOnce nfkc_cfInitOnce = U_INITONCE_INITIALIZER; | |
464 static icu::UInitOnce noopInitOnce = U_INITONCE_INITIALIZER; | 176 static icu::UInitOnce noopInitOnce = U_INITONCE_INITIALIZER; |
465 | 177 |
466 // UInitOnce singleton initialization function | 178 // UInitOnce singleton initialization functions |
467 static void U_CALLCONV initSingletons(const char *what, UErrorCode &errorCode) { | 179 static void U_CALLCONV initNFCSingleton(UErrorCode &errorCode) { |
468 if (uprv_strcmp(what, "nfc") == 0) { | 180 nfcSingleton=Norm2AllModes::createNFCInstance(errorCode); |
469 nfcSingleton = Norm2AllModes::createInstance(NULL, "nfc", errorCode)
; | 181 ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanu
p); |
470 } else if (uprv_strcmp(what, "nfkc") == 0) { | 182 } |
471 nfkcSingleton = Norm2AllModes::createInstance(NULL, "nfkc", errorCode
); | 183 |
472 } else if (uprv_strcmp(what, "nfkc_cf") == 0) { | 184 static void U_CALLCONV initNoopSingleton(UErrorCode &errorCode) { |
473 nfkc_cfSingleton = Norm2AllModes::createInstance(NULL, "nfkc_cf", errorC
ode); | 185 if(U_FAILURE(errorCode)) { |
474 } else if (uprv_strcmp(what, "noop") == 0) { | 186 return; |
475 noopSingleton = new NoopNormalizer2; | 187 } |
476 } else { | 188 noopSingleton=new NoopNormalizer2; |
477 U_ASSERT(FALSE); // Unknown singleton | 189 if(noopSingleton==NULL) { |
| 190 errorCode=U_MEMORY_ALLOCATION_ERROR; |
| 191 return; |
478 } | 192 } |
479 ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanu
p); | 193 ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanu
p); |
480 } | 194 } |
481 | 195 |
482 U_CDECL_BEGIN | 196 U_CDECL_BEGIN |
483 | 197 |
484 static void U_CALLCONV deleteNorm2AllModes(void *allModes) { | |
485 delete (Norm2AllModes *)allModes; | |
486 } | |
487 | |
488 static UBool U_CALLCONV uprv_normalizer2_cleanup() { | 198 static UBool U_CALLCONV uprv_normalizer2_cleanup() { |
489 delete nfcSingleton; | 199 delete nfcSingleton; |
490 nfcSingleton = NULL; | 200 nfcSingleton = NULL; |
491 delete nfkcSingleton; | |
492 nfkcSingleton = NULL; | |
493 delete nfkc_cfSingleton; | |
494 nfkc_cfSingleton = NULL; | |
495 delete noopSingleton; | 201 delete noopSingleton; |
496 noopSingleton = NULL; | 202 noopSingleton = NULL; |
497 uhash_close(cache); | |
498 cache=NULL; | |
499 nfcInitOnce.reset(); | 203 nfcInitOnce.reset(); |
500 nfkcInitOnce.reset(); | |
501 nfkc_cfInitOnce.reset(); | |
502 noopInitOnce.reset(); | 204 noopInitOnce.reset(); |
503 return TRUE; | 205 return TRUE; |
504 } | 206 } |
505 | 207 |
506 U_CDECL_END | 208 U_CDECL_END |
507 | 209 |
508 const Normalizer2 *Normalizer2Factory::getNFCInstance(UErrorCode &errorCode) { | 210 const Norm2AllModes * |
509 umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); | 211 Norm2AllModes::getNFCInstance(UErrorCode &errorCode) { |
510 return nfcSingleton!=NULL ? &nfcSingleton->comp : NULL; | 212 if(U_FAILURE(errorCode)) { return NULL; } |
| 213 umtx_initOnce(nfcInitOnce, &initNFCSingleton, errorCode); |
| 214 return nfcSingleton; |
511 } | 215 } |
512 | 216 |
513 const Normalizer2 *Normalizer2Factory::getNFDInstance(UErrorCode &errorCode) { | 217 const Normalizer2 * |
514 umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); | 218 Normalizer2::getNFCInstance(UErrorCode &errorCode) { |
515 return nfcSingleton!=NULL ? &nfcSingleton->decomp : NULL; | 219 const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); |
| 220 return allModes!=NULL ? &allModes->comp : NULL; |
| 221 } |
| 222 |
| 223 const Normalizer2 * |
| 224 Normalizer2::getNFDInstance(UErrorCode &errorCode) { |
| 225 const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); |
| 226 return allModes!=NULL ? &allModes->decomp : NULL; |
516 } | 227 } |
517 | 228 |
518 const Normalizer2 *Normalizer2Factory::getFCDInstance(UErrorCode &errorCode) { | 229 const Normalizer2 *Normalizer2Factory::getFCDInstance(UErrorCode &errorCode) { |
519 umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); | 230 const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); |
520 return nfcSingleton!=NULL ? &nfcSingleton->fcd : NULL; | 231 return allModes!=NULL ? &allModes->fcd : NULL; |
521 } | 232 } |
522 | 233 |
523 const Normalizer2 *Normalizer2Factory::getFCCInstance(UErrorCode &errorCode) { | 234 const Normalizer2 *Normalizer2Factory::getFCCInstance(UErrorCode &errorCode) { |
524 umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); | 235 const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); |
525 return nfcSingleton!=NULL ? &nfcSingleton->fcc : NULL; | 236 return allModes!=NULL ? &allModes->fcc : NULL; |
526 } | |
527 | |
528 const Normalizer2 *Normalizer2Factory::getNFKCInstance(UErrorCode &errorCode) { | |
529 umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); | |
530 return nfkcSingleton!=NULL ? &nfkcSingleton->comp : NULL; | |
531 } | |
532 | |
533 const Normalizer2 *Normalizer2Factory::getNFKDInstance(UErrorCode &errorCode) { | |
534 umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); | |
535 return nfkcSingleton!=NULL ? &nfkcSingleton->decomp : NULL; | |
536 } | |
537 | |
538 const Normalizer2 *Normalizer2Factory::getNFKC_CFInstance(UErrorCode &errorCode)
{ | |
539 umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode); | |
540 return nfkc_cfSingleton!=NULL ? &nfkc_cfSingleton->comp : NULL; | |
541 } | 237 } |
542 | 238 |
543 const Normalizer2 *Normalizer2Factory::getNoopInstance(UErrorCode &errorCode) { | 239 const Normalizer2 *Normalizer2Factory::getNoopInstance(UErrorCode &errorCode) { |
544 umtx_initOnce(noopInitOnce, &initSingletons, "noop", errorCode); | 240 if(U_FAILURE(errorCode)) { return NULL; } |
| 241 umtx_initOnce(noopInitOnce, &initNoopSingleton, errorCode); |
545 return noopSingleton; | 242 return noopSingleton; |
546 } | 243 } |
547 | 244 |
548 const Normalizer2 * | |
549 Normalizer2Factory::getInstance(UNormalizationMode mode, UErrorCode &errorCode)
{ | |
550 if(U_FAILURE(errorCode)) { | |
551 return NULL; | |
552 } | |
553 switch(mode) { | |
554 case UNORM_NFD: | |
555 return getNFDInstance(errorCode); | |
556 case UNORM_NFKD: | |
557 return getNFKDInstance(errorCode); | |
558 case UNORM_NFC: | |
559 return getNFCInstance(errorCode); | |
560 case UNORM_NFKC: | |
561 return getNFKCInstance(errorCode); | |
562 case UNORM_FCD: | |
563 return getFCDInstance(errorCode); | |
564 default: // UNORM_NONE | |
565 return getNoopInstance(errorCode); | |
566 } | |
567 } | |
568 | |
569 const Normalizer2Impl * | 245 const Normalizer2Impl * |
570 Normalizer2Factory::getNFCImpl(UErrorCode &errorCode) { | 246 Normalizer2Factory::getNFCImpl(UErrorCode &errorCode) { |
571 umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); | 247 const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); |
572 return nfcSingleton!=NULL ? &nfcSingleton->impl : NULL; | 248 return allModes!=NULL ? allModes->impl : NULL; |
573 } | 249 } |
574 | 250 |
575 const Normalizer2Impl * | 251 const Normalizer2Impl * |
576 Normalizer2Factory::getNFKCImpl(UErrorCode &errorCode) { | |
577 umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); | |
578 return nfkcSingleton!=NULL ? &nfkcSingleton->impl : NULL; | |
579 } | |
580 | |
581 const Normalizer2Impl * | |
582 Normalizer2Factory::getNFKC_CFImpl(UErrorCode &errorCode) { | |
583 umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode); | |
584 return nfkc_cfSingleton!=NULL ? &nfkc_cfSingleton->impl : NULL; | |
585 } | |
586 | |
587 const Normalizer2Impl * | |
588 Normalizer2Factory::getImpl(const Normalizer2 *norm2) { | 252 Normalizer2Factory::getImpl(const Normalizer2 *norm2) { |
589 return &((Normalizer2WithImpl *)norm2)->impl; | 253 return &((Normalizer2WithImpl *)norm2)->impl; |
590 } | 254 } |
591 | 255 |
592 const Normalizer2 * | |
593 Normalizer2::getNFCInstance(UErrorCode &errorCode) { | |
594 return Normalizer2Factory::getNFCInstance(errorCode); | |
595 } | |
596 | |
597 const Normalizer2 * | |
598 Normalizer2::getNFDInstance(UErrorCode &errorCode) { | |
599 return Normalizer2Factory::getNFDInstance(errorCode); | |
600 } | |
601 | |
602 const Normalizer2 * | |
603 Normalizer2::getNFKCInstance(UErrorCode &errorCode) { | |
604 return Normalizer2Factory::getNFKCInstance(errorCode); | |
605 } | |
606 | |
607 const Normalizer2 * | |
608 Normalizer2::getNFKDInstance(UErrorCode &errorCode) { | |
609 return Normalizer2Factory::getNFKDInstance(errorCode); | |
610 } | |
611 | |
612 const Normalizer2 * | |
613 Normalizer2::getNFKCCasefoldInstance(UErrorCode &errorCode) { | |
614 return Normalizer2Factory::getNFKC_CFInstance(errorCode); | |
615 } | |
616 | |
617 const Normalizer2 * | |
618 Normalizer2::getInstance(const char *packageName, | |
619 const char *name, | |
620 UNormalization2Mode mode, | |
621 UErrorCode &errorCode) { | |
622 if(U_FAILURE(errorCode)) { | |
623 return NULL; | |
624 } | |
625 if(name==NULL || *name==0) { | |
626 errorCode=U_ILLEGAL_ARGUMENT_ERROR; | |
627 return NULL; | |
628 } | |
629 Norm2AllModes *allModes=NULL; | |
630 if(packageName==NULL) { | |
631 if(0==uprv_strcmp(name, "nfc")) { | |
632 umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); | |
633 allModes=nfcSingleton; | |
634 } else if(0==uprv_strcmp(name, "nfkc")) { | |
635 umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); | |
636 allModes=nfkcSingleton; | |
637 } else if(0==uprv_strcmp(name, "nfkc_cf")) { | |
638 umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode
); | |
639 allModes=nfkc_cfSingleton; | |
640 } | |
641 } | |
642 if(allModes==NULL && U_SUCCESS(errorCode)) { | |
643 { | |
644 Mutex lock; | |
645 if(cache!=NULL) { | |
646 allModes=(Norm2AllModes *)uhash_get(cache, name); | |
647 } | |
648 } | |
649 if(allModes==NULL) { | |
650 LocalPointer<Norm2AllModes> localAllModes( | |
651 Norm2AllModes::createInstance(packageName, name, errorCode)); | |
652 if(U_SUCCESS(errorCode)) { | |
653 Mutex lock; | |
654 if(cache==NULL) { | |
655 cache=uhash_open(uhash_hashChars, uhash_compareChars, NULL,
&errorCode); | |
656 if(U_FAILURE(errorCode)) { | |
657 return NULL; | |
658 } | |
659 uhash_setKeyDeleter(cache, uprv_free); | |
660 uhash_setValueDeleter(cache, deleteNorm2AllModes); | |
661 } | |
662 void *temp=uhash_get(cache, name); | |
663 if(temp==NULL) { | |
664 int32_t keyLength=uprv_strlen(name)+1; | |
665 char *nameCopy=(char *)uprv_malloc(keyLength); | |
666 if(nameCopy==NULL) { | |
667 errorCode=U_MEMORY_ALLOCATION_ERROR; | |
668 return NULL; | |
669 } | |
670 uprv_memcpy(nameCopy, name, keyLength); | |
671 uhash_put(cache, nameCopy, allModes=localAllModes.orphan(),
&errorCode); | |
672 } else { | |
673 // race condition | |
674 allModes=(Norm2AllModes *)temp; | |
675 } | |
676 } | |
677 } | |
678 } | |
679 if(allModes!=NULL && U_SUCCESS(errorCode)) { | |
680 switch(mode) { | |
681 case UNORM2_COMPOSE: | |
682 return &allModes->comp; | |
683 case UNORM2_DECOMPOSE: | |
684 return &allModes->decomp; | |
685 case UNORM2_FCD: | |
686 return &allModes->fcd; | |
687 case UNORM2_COMPOSE_CONTIGUOUS: | |
688 return &allModes->fcc; | |
689 default: | |
690 break; // do nothing | |
691 } | |
692 } | |
693 return NULL; | |
694 } | |
695 | |
696 U_NAMESPACE_END | 256 U_NAMESPACE_END |
697 | 257 |
698 // C API ------------------------------------------------------------------- *** | 258 // C API ------------------------------------------------------------------- *** |
699 | 259 |
700 U_NAMESPACE_USE | 260 U_NAMESPACE_USE |
701 | 261 |
702 U_CAPI const UNormalizer2 * U_EXPORT2 | 262 U_CAPI const UNormalizer2 * U_EXPORT2 |
703 unorm2_getNFCInstance(UErrorCode *pErrorCode) { | 263 unorm2_getNFCInstance(UErrorCode *pErrorCode) { |
704 return (const UNormalizer2 *)Normalizer2::getNFCInstance(*pErrorCode); | 264 return (const UNormalizer2 *)Normalizer2::getNFCInstance(*pErrorCode); |
705 } | 265 } |
706 | 266 |
707 U_CAPI const UNormalizer2 * U_EXPORT2 | 267 U_CAPI const UNormalizer2 * U_EXPORT2 |
708 unorm2_getNFDInstance(UErrorCode *pErrorCode) { | 268 unorm2_getNFDInstance(UErrorCode *pErrorCode) { |
709 return (const UNormalizer2 *)Normalizer2::getNFDInstance(*pErrorCode); | 269 return (const UNormalizer2 *)Normalizer2::getNFDInstance(*pErrorCode); |
710 } | 270 } |
711 | 271 |
712 U_CAPI const UNormalizer2 * U_EXPORT2 | |
713 unorm2_getNFKCInstance(UErrorCode *pErrorCode) { | |
714 return (const UNormalizer2 *)Normalizer2::getNFKCInstance(*pErrorCode); | |
715 } | |
716 | |
717 U_CAPI const UNormalizer2 * U_EXPORT2 | |
718 unorm2_getNFKDInstance(UErrorCode *pErrorCode) { | |
719 return (const UNormalizer2 *)Normalizer2::getNFKDInstance(*pErrorCode); | |
720 } | |
721 | |
722 U_CAPI const UNormalizer2 * U_EXPORT2 | |
723 unorm2_getNFKCCasefoldInstance(UErrorCode *pErrorCode) { | |
724 return (const UNormalizer2 *)Normalizer2::getNFKCCasefoldInstance(*pErrorCod
e); | |
725 } | |
726 | |
727 U_CAPI const UNormalizer2 * U_EXPORT2 | |
728 unorm2_getInstance(const char *packageName, | |
729 const char *name, | |
730 UNormalization2Mode mode, | |
731 UErrorCode *pErrorCode) { | |
732 return (const UNormalizer2 *)Normalizer2::getInstance(packageName, name, mod
e, *pErrorCode); | |
733 } | |
734 | |
735 U_CAPI void U_EXPORT2 | 272 U_CAPI void U_EXPORT2 |
736 unorm2_close(UNormalizer2 *norm2) { | 273 unorm2_close(UNormalizer2 *norm2) { |
737 delete (Normalizer2 *)norm2; | 274 delete (Normalizer2 *)norm2; |
738 } | 275 } |
739 | 276 |
740 U_CAPI int32_t U_EXPORT2 | 277 U_CAPI int32_t U_EXPORT2 |
741 unorm2_normalize(const UNormalizer2 *norm2, | 278 unorm2_normalize(const UNormalizer2 *norm2, |
742 const UChar *src, int32_t length, | 279 const UChar *src, int32_t length, |
743 UChar *dest, int32_t capacity, | 280 UChar *dest, int32_t capacity, |
744 UErrorCode *pErrorCode) { | 281 UErrorCode *pErrorCode) { |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 U_CAPI UBool U_EXPORT2 | 492 U_CAPI UBool U_EXPORT2 |
956 unorm2_isInert(const UNormalizer2 *norm2, UChar32 c) { | 493 unorm2_isInert(const UNormalizer2 *norm2, UChar32 c) { |
957 return ((const Normalizer2 *)norm2)->isInert(c); | 494 return ((const Normalizer2 *)norm2)->isInert(c); |
958 } | 495 } |
959 | 496 |
960 // Some properties APIs ---------------------------------------------------- *** | 497 // Some properties APIs ---------------------------------------------------- *** |
961 | 498 |
962 U_CAPI uint8_t U_EXPORT2 | 499 U_CAPI uint8_t U_EXPORT2 |
963 u_getCombiningClass(UChar32 c) { | 500 u_getCombiningClass(UChar32 c) { |
964 UErrorCode errorCode=U_ZERO_ERROR; | 501 UErrorCode errorCode=U_ZERO_ERROR; |
965 const Normalizer2 *nfd=Normalizer2Factory::getNFDInstance(errorCode); | 502 const Normalizer2 *nfd=Normalizer2::getNFDInstance(errorCode); |
966 if(U_SUCCESS(errorCode)) { | 503 if(U_SUCCESS(errorCode)) { |
967 return nfd->getCombiningClass(c); | 504 return nfd->getCombiningClass(c); |
968 } else { | 505 } else { |
969 return 0; | 506 return 0; |
970 } | 507 } |
971 } | 508 } |
972 | 509 |
973 U_CFUNC UNormalizationCheckResult | |
974 unorm_getQuickCheck(UChar32 c, UNormalizationMode mode) { | |
975 if(mode<=UNORM_NONE || UNORM_FCD<=mode) { | |
976 return UNORM_YES; | |
977 } | |
978 UErrorCode errorCode=U_ZERO_ERROR; | |
979 const Normalizer2 *norm2=Normalizer2Factory::getInstance(mode, errorCode); | |
980 if(U_SUCCESS(errorCode)) { | |
981 return ((const Normalizer2WithImpl *)norm2)->getQuickCheck(c); | |
982 } else { | |
983 return UNORM_MAYBE; | |
984 } | |
985 } | |
986 | |
987 U_CFUNC uint16_t | 510 U_CFUNC uint16_t |
988 unorm_getFCD16(UChar32 c) { | 511 unorm_getFCD16(UChar32 c) { |
989 UErrorCode errorCode=U_ZERO_ERROR; | 512 UErrorCode errorCode=U_ZERO_ERROR; |
990 const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(errorCode); | 513 const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(errorCode); |
991 if(U_SUCCESS(errorCode)) { | 514 if(U_SUCCESS(errorCode)) { |
992 return impl->getFCD16(c); | 515 return impl->getFCD16(c); |
993 } else { | 516 } else { |
994 return 0; | 517 return 0; |
995 } | 518 } |
996 } | 519 } |
997 | 520 |
998 #endif // !UCONFIG_NO_NORMALIZATION | 521 #endif // !UCONFIG_NO_NORMALIZATION |
OLD | NEW |