| 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 |