1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/common/normalizer2.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,998 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* 1.7 +* Copyright (C) 2009-2013, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +******************************************************************************* 1.11 +* file name: normalizer2.cpp 1.12 +* encoding: US-ASCII 1.13 +* tab size: 8 (not used) 1.14 +* indentation:4 1.15 +* 1.16 +* created on: 2009nov22 1.17 +* created by: Markus W. Scherer 1.18 +*/ 1.19 + 1.20 +#include "unicode/utypes.h" 1.21 + 1.22 +#if !UCONFIG_NO_NORMALIZATION 1.23 + 1.24 +#include "unicode/localpointer.h" 1.25 +#include "unicode/normalizer2.h" 1.26 +#include "unicode/unistr.h" 1.27 +#include "unicode/unorm.h" 1.28 +#include "cpputils.h" 1.29 +#include "cstring.h" 1.30 +#include "mutex.h" 1.31 +#include "normalizer2impl.h" 1.32 +#include "uassert.h" 1.33 +#include "ucln_cmn.h" 1.34 +#include "uhash.h" 1.35 + 1.36 +U_NAMESPACE_BEGIN 1.37 + 1.38 +// Public API dispatch via Normalizer2 subclasses -------------------------- *** 1.39 + 1.40 +Normalizer2::~Normalizer2() {} 1.41 + 1.42 +UBool 1.43 +Normalizer2::getRawDecomposition(UChar32, UnicodeString &) const { 1.44 + return FALSE; 1.45 +} 1.46 + 1.47 +UChar32 1.48 +Normalizer2::composePair(UChar32, UChar32) const { 1.49 + return U_SENTINEL; 1.50 +} 1.51 + 1.52 +uint8_t 1.53 +Normalizer2::getCombiningClass(UChar32 /*c*/) const { 1.54 + return 0; 1.55 +} 1.56 + 1.57 +// Normalizer2 implementation for the old UNORM_NONE. 1.58 +class NoopNormalizer2 : public Normalizer2 { 1.59 + virtual ~NoopNormalizer2(); 1.60 + 1.61 + virtual UnicodeString & 1.62 + normalize(const UnicodeString &src, 1.63 + UnicodeString &dest, 1.64 + UErrorCode &errorCode) const { 1.65 + if(U_SUCCESS(errorCode)) { 1.66 + if(&dest!=&src) { 1.67 + dest=src; 1.68 + } else { 1.69 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.70 + } 1.71 + } 1.72 + return dest; 1.73 + } 1.74 + virtual UnicodeString & 1.75 + normalizeSecondAndAppend(UnicodeString &first, 1.76 + const UnicodeString &second, 1.77 + UErrorCode &errorCode) const { 1.78 + if(U_SUCCESS(errorCode)) { 1.79 + if(&first!=&second) { 1.80 + first.append(second); 1.81 + } else { 1.82 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.83 + } 1.84 + } 1.85 + return first; 1.86 + } 1.87 + virtual UnicodeString & 1.88 + append(UnicodeString &first, 1.89 + const UnicodeString &second, 1.90 + UErrorCode &errorCode) const { 1.91 + if(U_SUCCESS(errorCode)) { 1.92 + if(&first!=&second) { 1.93 + first.append(second); 1.94 + } else { 1.95 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.96 + } 1.97 + } 1.98 + return first; 1.99 + } 1.100 + virtual UBool 1.101 + getDecomposition(UChar32, UnicodeString &) const { 1.102 + return FALSE; 1.103 + } 1.104 + // No need to override the default getRawDecomposition(). 1.105 + virtual UBool 1.106 + isNormalized(const UnicodeString &, UErrorCode &) const { 1.107 + return TRUE; 1.108 + } 1.109 + virtual UNormalizationCheckResult 1.110 + quickCheck(const UnicodeString &, UErrorCode &) const { 1.111 + return UNORM_YES; 1.112 + } 1.113 + virtual int32_t 1.114 + spanQuickCheckYes(const UnicodeString &s, UErrorCode &) const { 1.115 + return s.length(); 1.116 + } 1.117 + virtual UBool hasBoundaryBefore(UChar32) const { return TRUE; } 1.118 + virtual UBool hasBoundaryAfter(UChar32) const { return TRUE; } 1.119 + virtual UBool isInert(UChar32) const { return TRUE; } 1.120 +}; 1.121 + 1.122 +NoopNormalizer2::~NoopNormalizer2() {} 1.123 + 1.124 +// Intermediate class: 1.125 +// Has Normalizer2Impl and does boilerplate argument checking and setup. 1.126 +class Normalizer2WithImpl : public Normalizer2 { 1.127 +public: 1.128 + Normalizer2WithImpl(const Normalizer2Impl &ni) : impl(ni) {} 1.129 + virtual ~Normalizer2WithImpl(); 1.130 + 1.131 + // normalize 1.132 + virtual UnicodeString & 1.133 + normalize(const UnicodeString &src, 1.134 + UnicodeString &dest, 1.135 + UErrorCode &errorCode) const { 1.136 + if(U_FAILURE(errorCode)) { 1.137 + dest.setToBogus(); 1.138 + return dest; 1.139 + } 1.140 + const UChar *sArray=src.getBuffer(); 1.141 + if(&dest==&src || sArray==NULL) { 1.142 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.143 + dest.setToBogus(); 1.144 + return dest; 1.145 + } 1.146 + dest.remove(); 1.147 + ReorderingBuffer buffer(impl, dest); 1.148 + if(buffer.init(src.length(), errorCode)) { 1.149 + normalize(sArray, sArray+src.length(), buffer, errorCode); 1.150 + } 1.151 + return dest; 1.152 + } 1.153 + virtual void 1.154 + normalize(const UChar *src, const UChar *limit, 1.155 + ReorderingBuffer &buffer, UErrorCode &errorCode) const = 0; 1.156 + 1.157 + // normalize and append 1.158 + virtual UnicodeString & 1.159 + normalizeSecondAndAppend(UnicodeString &first, 1.160 + const UnicodeString &second, 1.161 + UErrorCode &errorCode) const { 1.162 + return normalizeSecondAndAppend(first, second, TRUE, errorCode); 1.163 + } 1.164 + virtual UnicodeString & 1.165 + append(UnicodeString &first, 1.166 + const UnicodeString &second, 1.167 + UErrorCode &errorCode) const { 1.168 + return normalizeSecondAndAppend(first, second, FALSE, errorCode); 1.169 + } 1.170 + UnicodeString & 1.171 + normalizeSecondAndAppend(UnicodeString &first, 1.172 + const UnicodeString &second, 1.173 + UBool doNormalize, 1.174 + UErrorCode &errorCode) const { 1.175 + uprv_checkCanGetBuffer(first, errorCode); 1.176 + if(U_FAILURE(errorCode)) { 1.177 + return first; 1.178 + } 1.179 + const UChar *secondArray=second.getBuffer(); 1.180 + if(&first==&second || secondArray==NULL) { 1.181 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.182 + return first; 1.183 + } 1.184 + int32_t firstLength=first.length(); 1.185 + UnicodeString safeMiddle; 1.186 + { 1.187 + ReorderingBuffer buffer(impl, first); 1.188 + if(buffer.init(firstLength+second.length(), errorCode)) { 1.189 + normalizeAndAppend(secondArray, secondArray+second.length(), doNormalize, 1.190 + safeMiddle, buffer, errorCode); 1.191 + } 1.192 + } // The ReorderingBuffer destructor finalizes the first string. 1.193 + if(U_FAILURE(errorCode)) { 1.194 + // Restore the modified suffix of the first string. 1.195 + first.replace(firstLength-safeMiddle.length(), 0x7fffffff, safeMiddle); 1.196 + } 1.197 + return first; 1.198 + } 1.199 + virtual void 1.200 + normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, 1.201 + UnicodeString &safeMiddle, 1.202 + ReorderingBuffer &buffer, UErrorCode &errorCode) const = 0; 1.203 + virtual UBool 1.204 + getDecomposition(UChar32 c, UnicodeString &decomposition) const { 1.205 + UChar buffer[4]; 1.206 + int32_t length; 1.207 + const UChar *d=impl.getDecomposition(c, buffer, length); 1.208 + if(d==NULL) { 1.209 + return FALSE; 1.210 + } 1.211 + if(d==buffer) { 1.212 + decomposition.setTo(buffer, length); // copy the string (Jamos from Hangul syllable c) 1.213 + } else { 1.214 + decomposition.setTo(FALSE, d, length); // read-only alias 1.215 + } 1.216 + return TRUE; 1.217 + } 1.218 + virtual UBool 1.219 + getRawDecomposition(UChar32 c, UnicodeString &decomposition) const { 1.220 + UChar buffer[30]; 1.221 + int32_t length; 1.222 + const UChar *d=impl.getRawDecomposition(c, buffer, length); 1.223 + if(d==NULL) { 1.224 + return FALSE; 1.225 + } 1.226 + if(d==buffer) { 1.227 + decomposition.setTo(buffer, length); // copy the string (algorithmic decomposition) 1.228 + } else { 1.229 + decomposition.setTo(FALSE, d, length); // read-only alias 1.230 + } 1.231 + return TRUE; 1.232 + } 1.233 + virtual UChar32 1.234 + composePair(UChar32 a, UChar32 b) const { 1.235 + return impl.composePair(a, b); 1.236 + } 1.237 + 1.238 + virtual uint8_t 1.239 + getCombiningClass(UChar32 c) const { 1.240 + return impl.getCC(impl.getNorm16(c)); 1.241 + } 1.242 + 1.243 + // quick checks 1.244 + virtual UBool 1.245 + isNormalized(const UnicodeString &s, UErrorCode &errorCode) const { 1.246 + if(U_FAILURE(errorCode)) { 1.247 + return FALSE; 1.248 + } 1.249 + const UChar *sArray=s.getBuffer(); 1.250 + if(sArray==NULL) { 1.251 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.252 + return FALSE; 1.253 + } 1.254 + const UChar *sLimit=sArray+s.length(); 1.255 + return sLimit==spanQuickCheckYes(sArray, sLimit, errorCode); 1.256 + } 1.257 + virtual UNormalizationCheckResult 1.258 + quickCheck(const UnicodeString &s, UErrorCode &errorCode) const { 1.259 + return Normalizer2WithImpl::isNormalized(s, errorCode) ? UNORM_YES : UNORM_NO; 1.260 + } 1.261 + virtual int32_t 1.262 + spanQuickCheckYes(const UnicodeString &s, UErrorCode &errorCode) const { 1.263 + if(U_FAILURE(errorCode)) { 1.264 + return 0; 1.265 + } 1.266 + const UChar *sArray=s.getBuffer(); 1.267 + if(sArray==NULL) { 1.268 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.269 + return 0; 1.270 + } 1.271 + return (int32_t)(spanQuickCheckYes(sArray, sArray+s.length(), errorCode)-sArray); 1.272 + } 1.273 + virtual const UChar * 1.274 + spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const = 0; 1.275 + 1.276 + virtual UNormalizationCheckResult getQuickCheck(UChar32) const { 1.277 + return UNORM_YES; 1.278 + } 1.279 + 1.280 + const Normalizer2Impl &impl; 1.281 +}; 1.282 + 1.283 +Normalizer2WithImpl::~Normalizer2WithImpl() {} 1.284 + 1.285 +class DecomposeNormalizer2 : public Normalizer2WithImpl { 1.286 +public: 1.287 + DecomposeNormalizer2(const Normalizer2Impl &ni) : Normalizer2WithImpl(ni) {} 1.288 + virtual ~DecomposeNormalizer2(); 1.289 + 1.290 +private: 1.291 + virtual void 1.292 + normalize(const UChar *src, const UChar *limit, 1.293 + ReorderingBuffer &buffer, UErrorCode &errorCode) const { 1.294 + impl.decompose(src, limit, &buffer, errorCode); 1.295 + } 1.296 + using Normalizer2WithImpl::normalize; // Avoid warning about hiding base class function. 1.297 + virtual void 1.298 + normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, 1.299 + UnicodeString &safeMiddle, 1.300 + ReorderingBuffer &buffer, UErrorCode &errorCode) const { 1.301 + impl.decomposeAndAppend(src, limit, doNormalize, safeMiddle, buffer, errorCode); 1.302 + } 1.303 + virtual const UChar * 1.304 + spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const { 1.305 + return impl.decompose(src, limit, NULL, errorCode); 1.306 + } 1.307 + using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding base class function. 1.308 + virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const { 1.309 + return impl.isDecompYes(impl.getNorm16(c)) ? UNORM_YES : UNORM_NO; 1.310 + } 1.311 + virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasDecompBoundary(c, TRUE); } 1.312 + virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasDecompBoundary(c, FALSE); } 1.313 + virtual UBool isInert(UChar32 c) const { return impl.isDecompInert(c); } 1.314 +}; 1.315 + 1.316 +DecomposeNormalizer2::~DecomposeNormalizer2() {} 1.317 + 1.318 +class ComposeNormalizer2 : public Normalizer2WithImpl { 1.319 +public: 1.320 + ComposeNormalizer2(const Normalizer2Impl &ni, UBool fcc) : 1.321 + Normalizer2WithImpl(ni), onlyContiguous(fcc) {} 1.322 + virtual ~ComposeNormalizer2(); 1.323 + 1.324 +private: 1.325 + virtual void 1.326 + normalize(const UChar *src, const UChar *limit, 1.327 + ReorderingBuffer &buffer, UErrorCode &errorCode) const { 1.328 + impl.compose(src, limit, onlyContiguous, TRUE, buffer, errorCode); 1.329 + } 1.330 + using Normalizer2WithImpl::normalize; // Avoid warning about hiding base class function. 1.331 + virtual void 1.332 + normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, 1.333 + UnicodeString &safeMiddle, 1.334 + ReorderingBuffer &buffer, UErrorCode &errorCode) const { 1.335 + impl.composeAndAppend(src, limit, doNormalize, onlyContiguous, safeMiddle, buffer, errorCode); 1.336 + } 1.337 + 1.338 + virtual UBool 1.339 + isNormalized(const UnicodeString &s, UErrorCode &errorCode) const { 1.340 + if(U_FAILURE(errorCode)) { 1.341 + return FALSE; 1.342 + } 1.343 + const UChar *sArray=s.getBuffer(); 1.344 + if(sArray==NULL) { 1.345 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.346 + return FALSE; 1.347 + } 1.348 + UnicodeString temp; 1.349 + ReorderingBuffer buffer(impl, temp); 1.350 + if(!buffer.init(5, errorCode)) { // small destCapacity for substring normalization 1.351 + return FALSE; 1.352 + } 1.353 + return impl.compose(sArray, sArray+s.length(), onlyContiguous, FALSE, buffer, errorCode); 1.354 + } 1.355 + virtual UNormalizationCheckResult 1.356 + quickCheck(const UnicodeString &s, UErrorCode &errorCode) const { 1.357 + if(U_FAILURE(errorCode)) { 1.358 + return UNORM_MAYBE; 1.359 + } 1.360 + const UChar *sArray=s.getBuffer(); 1.361 + if(sArray==NULL) { 1.362 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.363 + return UNORM_MAYBE; 1.364 + } 1.365 + UNormalizationCheckResult qcResult=UNORM_YES; 1.366 + impl.composeQuickCheck(sArray, sArray+s.length(), onlyContiguous, &qcResult); 1.367 + return qcResult; 1.368 + } 1.369 + virtual const UChar * 1.370 + spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &) const { 1.371 + return impl.composeQuickCheck(src, limit, onlyContiguous, NULL); 1.372 + } 1.373 + using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding base class function. 1.374 + virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const { 1.375 + return impl.getCompQuickCheck(impl.getNorm16(c)); 1.376 + } 1.377 + virtual UBool hasBoundaryBefore(UChar32 c) const { 1.378 + return impl.hasCompBoundaryBefore(c); 1.379 + } 1.380 + virtual UBool hasBoundaryAfter(UChar32 c) const { 1.381 + return impl.hasCompBoundaryAfter(c, onlyContiguous, FALSE); 1.382 + } 1.383 + virtual UBool isInert(UChar32 c) const { 1.384 + return impl.hasCompBoundaryAfter(c, onlyContiguous, TRUE); 1.385 + } 1.386 + 1.387 + const UBool onlyContiguous; 1.388 +}; 1.389 + 1.390 +ComposeNormalizer2::~ComposeNormalizer2() {} 1.391 + 1.392 +class FCDNormalizer2 : public Normalizer2WithImpl { 1.393 +public: 1.394 + FCDNormalizer2(const Normalizer2Impl &ni) : Normalizer2WithImpl(ni) {} 1.395 + virtual ~FCDNormalizer2(); 1.396 + 1.397 +private: 1.398 + virtual void 1.399 + normalize(const UChar *src, const UChar *limit, 1.400 + ReorderingBuffer &buffer, UErrorCode &errorCode) const { 1.401 + impl.makeFCD(src, limit, &buffer, errorCode); 1.402 + } 1.403 + using Normalizer2WithImpl::normalize; // Avoid warning about hiding base class function. 1.404 + virtual void 1.405 + normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, 1.406 + UnicodeString &safeMiddle, 1.407 + ReorderingBuffer &buffer, UErrorCode &errorCode) const { 1.408 + impl.makeFCDAndAppend(src, limit, doNormalize, safeMiddle, buffer, errorCode); 1.409 + } 1.410 + virtual const UChar * 1.411 + spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const { 1.412 + return impl.makeFCD(src, limit, NULL, errorCode); 1.413 + } 1.414 + using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding base class function. 1.415 + virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasFCDBoundaryBefore(c); } 1.416 + virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasFCDBoundaryAfter(c); } 1.417 + virtual UBool isInert(UChar32 c) const { return impl.isFCDInert(c); } 1.418 +}; 1.419 + 1.420 +FCDNormalizer2::~FCDNormalizer2() {} 1.421 + 1.422 +// instance cache ---------------------------------------------------------- *** 1.423 + 1.424 +struct Norm2AllModes : public UMemory { 1.425 + static Norm2AllModes *createInstance(const char *packageName, 1.426 + const char *name, 1.427 + UErrorCode &errorCode); 1.428 + Norm2AllModes() : comp(impl, FALSE), decomp(impl), fcd(impl), fcc(impl, TRUE) {} 1.429 + 1.430 + Normalizer2Impl impl; 1.431 + ComposeNormalizer2 comp; 1.432 + DecomposeNormalizer2 decomp; 1.433 + FCDNormalizer2 fcd; 1.434 + ComposeNormalizer2 fcc; 1.435 +}; 1.436 + 1.437 +Norm2AllModes * 1.438 +Norm2AllModes::createInstance(const char *packageName, 1.439 + const char *name, 1.440 + UErrorCode &errorCode) { 1.441 + if(U_FAILURE(errorCode)) { 1.442 + return NULL; 1.443 + } 1.444 + LocalPointer<Norm2AllModes> allModes(new Norm2AllModes); 1.445 + if(allModes.isNull()) { 1.446 + errorCode=U_MEMORY_ALLOCATION_ERROR; 1.447 + return NULL; 1.448 + } 1.449 + allModes->impl.load(packageName, name, errorCode); 1.450 + return U_SUCCESS(errorCode) ? allModes.orphan() : NULL; 1.451 +} 1.452 + 1.453 +U_CDECL_BEGIN 1.454 +static UBool U_CALLCONV uprv_normalizer2_cleanup(); 1.455 +U_CDECL_END 1.456 + 1.457 + 1.458 +static Norm2AllModes *nfcSingleton; 1.459 +static Norm2AllModes *nfkcSingleton; 1.460 +static Norm2AllModes *nfkc_cfSingleton; 1.461 +static Normalizer2 *noopSingleton; 1.462 +static UHashtable *cache=NULL; 1.463 + 1.464 +static icu::UInitOnce nfcInitOnce = U_INITONCE_INITIALIZER; 1.465 +static icu::UInitOnce nfkcInitOnce = U_INITONCE_INITIALIZER; 1.466 +static icu::UInitOnce nfkc_cfInitOnce = U_INITONCE_INITIALIZER; 1.467 +static icu::UInitOnce noopInitOnce = U_INITONCE_INITIALIZER; 1.468 + 1.469 +// UInitOnce singleton initialization function 1.470 +static void U_CALLCONV initSingletons(const char *what, UErrorCode &errorCode) { 1.471 + if (uprv_strcmp(what, "nfc") == 0) { 1.472 + nfcSingleton = Norm2AllModes::createInstance(NULL, "nfc", errorCode); 1.473 + } else if (uprv_strcmp(what, "nfkc") == 0) { 1.474 + nfkcSingleton = Norm2AllModes::createInstance(NULL, "nfkc", errorCode); 1.475 + } else if (uprv_strcmp(what, "nfkc_cf") == 0) { 1.476 + nfkc_cfSingleton = Norm2AllModes::createInstance(NULL, "nfkc_cf", errorCode); 1.477 + } else if (uprv_strcmp(what, "noop") == 0) { 1.478 + noopSingleton = new NoopNormalizer2; 1.479 + } else { 1.480 + U_ASSERT(FALSE); // Unknown singleton 1.481 + } 1.482 + ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); 1.483 +} 1.484 + 1.485 +U_CDECL_BEGIN 1.486 + 1.487 +static void U_CALLCONV deleteNorm2AllModes(void *allModes) { 1.488 + delete (Norm2AllModes *)allModes; 1.489 +} 1.490 + 1.491 +static UBool U_CALLCONV uprv_normalizer2_cleanup() { 1.492 + delete nfcSingleton; 1.493 + nfcSingleton = NULL; 1.494 + delete nfkcSingleton; 1.495 + nfkcSingleton = NULL; 1.496 + delete nfkc_cfSingleton; 1.497 + nfkc_cfSingleton = NULL; 1.498 + delete noopSingleton; 1.499 + noopSingleton = NULL; 1.500 + uhash_close(cache); 1.501 + cache=NULL; 1.502 + nfcInitOnce.reset(); 1.503 + nfkcInitOnce.reset(); 1.504 + nfkc_cfInitOnce.reset(); 1.505 + noopInitOnce.reset(); 1.506 + return TRUE; 1.507 +} 1.508 + 1.509 +U_CDECL_END 1.510 + 1.511 +const Normalizer2 *Normalizer2Factory::getNFCInstance(UErrorCode &errorCode) { 1.512 + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); 1.513 + return nfcSingleton!=NULL ? &nfcSingleton->comp : NULL; 1.514 +} 1.515 + 1.516 +const Normalizer2 *Normalizer2Factory::getNFDInstance(UErrorCode &errorCode) { 1.517 + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); 1.518 + return nfcSingleton!=NULL ? &nfcSingleton->decomp : NULL; 1.519 +} 1.520 + 1.521 +const Normalizer2 *Normalizer2Factory::getFCDInstance(UErrorCode &errorCode) { 1.522 + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); 1.523 + return nfcSingleton!=NULL ? &nfcSingleton->fcd : NULL; 1.524 +} 1.525 + 1.526 +const Normalizer2 *Normalizer2Factory::getFCCInstance(UErrorCode &errorCode) { 1.527 + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); 1.528 + return nfcSingleton!=NULL ? &nfcSingleton->fcc : NULL; 1.529 +} 1.530 + 1.531 +const Normalizer2 *Normalizer2Factory::getNFKCInstance(UErrorCode &errorCode) { 1.532 + umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); 1.533 + return nfkcSingleton!=NULL ? &nfkcSingleton->comp : NULL; 1.534 +} 1.535 + 1.536 +const Normalizer2 *Normalizer2Factory::getNFKDInstance(UErrorCode &errorCode) { 1.537 + umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); 1.538 + return nfkcSingleton!=NULL ? &nfkcSingleton->decomp : NULL; 1.539 +} 1.540 + 1.541 +const Normalizer2 *Normalizer2Factory::getNFKC_CFInstance(UErrorCode &errorCode) { 1.542 + umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode); 1.543 + return nfkc_cfSingleton!=NULL ? &nfkc_cfSingleton->comp : NULL; 1.544 +} 1.545 + 1.546 +const Normalizer2 *Normalizer2Factory::getNoopInstance(UErrorCode &errorCode) { 1.547 + umtx_initOnce(noopInitOnce, &initSingletons, "noop", errorCode); 1.548 + return noopSingleton; 1.549 +} 1.550 + 1.551 +const Normalizer2 * 1.552 +Normalizer2Factory::getInstance(UNormalizationMode mode, UErrorCode &errorCode) { 1.553 + if(U_FAILURE(errorCode)) { 1.554 + return NULL; 1.555 + } 1.556 + switch(mode) { 1.557 + case UNORM_NFD: 1.558 + return getNFDInstance(errorCode); 1.559 + case UNORM_NFKD: 1.560 + return getNFKDInstance(errorCode); 1.561 + case UNORM_NFC: 1.562 + return getNFCInstance(errorCode); 1.563 + case UNORM_NFKC: 1.564 + return getNFKCInstance(errorCode); 1.565 + case UNORM_FCD: 1.566 + return getFCDInstance(errorCode); 1.567 + default: // UNORM_NONE 1.568 + return getNoopInstance(errorCode); 1.569 + } 1.570 +} 1.571 + 1.572 +const Normalizer2Impl * 1.573 +Normalizer2Factory::getNFCImpl(UErrorCode &errorCode) { 1.574 + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); 1.575 + return nfcSingleton!=NULL ? &nfcSingleton->impl : NULL; 1.576 +} 1.577 + 1.578 +const Normalizer2Impl * 1.579 +Normalizer2Factory::getNFKCImpl(UErrorCode &errorCode) { 1.580 + umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); 1.581 + return nfkcSingleton!=NULL ? &nfkcSingleton->impl : NULL; 1.582 +} 1.583 + 1.584 +const Normalizer2Impl * 1.585 +Normalizer2Factory::getNFKC_CFImpl(UErrorCode &errorCode) { 1.586 + umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode); 1.587 + return nfkc_cfSingleton!=NULL ? &nfkc_cfSingleton->impl : NULL; 1.588 +} 1.589 + 1.590 +const Normalizer2Impl * 1.591 +Normalizer2Factory::getImpl(const Normalizer2 *norm2) { 1.592 + return &((Normalizer2WithImpl *)norm2)->impl; 1.593 +} 1.594 + 1.595 +const Normalizer2 * 1.596 +Normalizer2::getNFCInstance(UErrorCode &errorCode) { 1.597 + return Normalizer2Factory::getNFCInstance(errorCode); 1.598 +} 1.599 + 1.600 +const Normalizer2 * 1.601 +Normalizer2::getNFDInstance(UErrorCode &errorCode) { 1.602 + return Normalizer2Factory::getNFDInstance(errorCode); 1.603 +} 1.604 + 1.605 +const Normalizer2 * 1.606 +Normalizer2::getNFKCInstance(UErrorCode &errorCode) { 1.607 + return Normalizer2Factory::getNFKCInstance(errorCode); 1.608 +} 1.609 + 1.610 +const Normalizer2 * 1.611 +Normalizer2::getNFKDInstance(UErrorCode &errorCode) { 1.612 + return Normalizer2Factory::getNFKDInstance(errorCode); 1.613 +} 1.614 + 1.615 +const Normalizer2 * 1.616 +Normalizer2::getNFKCCasefoldInstance(UErrorCode &errorCode) { 1.617 + return Normalizer2Factory::getNFKC_CFInstance(errorCode); 1.618 +} 1.619 + 1.620 +const Normalizer2 * 1.621 +Normalizer2::getInstance(const char *packageName, 1.622 + const char *name, 1.623 + UNormalization2Mode mode, 1.624 + UErrorCode &errorCode) { 1.625 + if(U_FAILURE(errorCode)) { 1.626 + return NULL; 1.627 + } 1.628 + if(name==NULL || *name==0) { 1.629 + errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.630 + return NULL; 1.631 + } 1.632 + Norm2AllModes *allModes=NULL; 1.633 + if(packageName==NULL) { 1.634 + if(0==uprv_strcmp(name, "nfc")) { 1.635 + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); 1.636 + allModes=nfcSingleton; 1.637 + } else if(0==uprv_strcmp(name, "nfkc")) { 1.638 + umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); 1.639 + allModes=nfkcSingleton; 1.640 + } else if(0==uprv_strcmp(name, "nfkc_cf")) { 1.641 + umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode); 1.642 + allModes=nfkc_cfSingleton; 1.643 + } 1.644 + } 1.645 + if(allModes==NULL && U_SUCCESS(errorCode)) { 1.646 + { 1.647 + Mutex lock; 1.648 + if(cache!=NULL) { 1.649 + allModes=(Norm2AllModes *)uhash_get(cache, name); 1.650 + } 1.651 + } 1.652 + if(allModes==NULL) { 1.653 + LocalPointer<Norm2AllModes> localAllModes( 1.654 + Norm2AllModes::createInstance(packageName, name, errorCode)); 1.655 + if(U_SUCCESS(errorCode)) { 1.656 + Mutex lock; 1.657 + if(cache==NULL) { 1.658 + cache=uhash_open(uhash_hashChars, uhash_compareChars, NULL, &errorCode); 1.659 + if(U_FAILURE(errorCode)) { 1.660 + return NULL; 1.661 + } 1.662 + uhash_setKeyDeleter(cache, uprv_free); 1.663 + uhash_setValueDeleter(cache, deleteNorm2AllModes); 1.664 + } 1.665 + void *temp=uhash_get(cache, name); 1.666 + if(temp==NULL) { 1.667 + int32_t keyLength=uprv_strlen(name)+1; 1.668 + char *nameCopy=(char *)uprv_malloc(keyLength); 1.669 + if(nameCopy==NULL) { 1.670 + errorCode=U_MEMORY_ALLOCATION_ERROR; 1.671 + return NULL; 1.672 + } 1.673 + uprv_memcpy(nameCopy, name, keyLength); 1.674 + uhash_put(cache, nameCopy, allModes=localAllModes.orphan(), &errorCode); 1.675 + } else { 1.676 + // race condition 1.677 + allModes=(Norm2AllModes *)temp; 1.678 + } 1.679 + } 1.680 + } 1.681 + } 1.682 + if(allModes!=NULL && U_SUCCESS(errorCode)) { 1.683 + switch(mode) { 1.684 + case UNORM2_COMPOSE: 1.685 + return &allModes->comp; 1.686 + case UNORM2_DECOMPOSE: 1.687 + return &allModes->decomp; 1.688 + case UNORM2_FCD: 1.689 + return &allModes->fcd; 1.690 + case UNORM2_COMPOSE_CONTIGUOUS: 1.691 + return &allModes->fcc; 1.692 + default: 1.693 + break; // do nothing 1.694 + } 1.695 + } 1.696 + return NULL; 1.697 +} 1.698 + 1.699 +U_NAMESPACE_END 1.700 + 1.701 +// C API ------------------------------------------------------------------- *** 1.702 + 1.703 +U_NAMESPACE_USE 1.704 + 1.705 +U_CAPI const UNormalizer2 * U_EXPORT2 1.706 +unorm2_getNFCInstance(UErrorCode *pErrorCode) { 1.707 + return (const UNormalizer2 *)Normalizer2::getNFCInstance(*pErrorCode); 1.708 +} 1.709 + 1.710 +U_CAPI const UNormalizer2 * U_EXPORT2 1.711 +unorm2_getNFDInstance(UErrorCode *pErrorCode) { 1.712 + return (const UNormalizer2 *)Normalizer2::getNFDInstance(*pErrorCode); 1.713 +} 1.714 + 1.715 +U_CAPI const UNormalizer2 * U_EXPORT2 1.716 +unorm2_getNFKCInstance(UErrorCode *pErrorCode) { 1.717 + return (const UNormalizer2 *)Normalizer2::getNFKCInstance(*pErrorCode); 1.718 +} 1.719 + 1.720 +U_CAPI const UNormalizer2 * U_EXPORT2 1.721 +unorm2_getNFKDInstance(UErrorCode *pErrorCode) { 1.722 + return (const UNormalizer2 *)Normalizer2::getNFKDInstance(*pErrorCode); 1.723 +} 1.724 + 1.725 +U_CAPI const UNormalizer2 * U_EXPORT2 1.726 +unorm2_getNFKCCasefoldInstance(UErrorCode *pErrorCode) { 1.727 + return (const UNormalizer2 *)Normalizer2::getNFKCCasefoldInstance(*pErrorCode); 1.728 +} 1.729 + 1.730 +U_CAPI const UNormalizer2 * U_EXPORT2 1.731 +unorm2_getInstance(const char *packageName, 1.732 + const char *name, 1.733 + UNormalization2Mode mode, 1.734 + UErrorCode *pErrorCode) { 1.735 + return (const UNormalizer2 *)Normalizer2::getInstance(packageName, name, mode, *pErrorCode); 1.736 +} 1.737 + 1.738 +U_CAPI void U_EXPORT2 1.739 +unorm2_close(UNormalizer2 *norm2) { 1.740 + delete (Normalizer2 *)norm2; 1.741 +} 1.742 + 1.743 +U_CAPI int32_t U_EXPORT2 1.744 +unorm2_normalize(const UNormalizer2 *norm2, 1.745 + const UChar *src, int32_t length, 1.746 + UChar *dest, int32_t capacity, 1.747 + UErrorCode *pErrorCode) { 1.748 + if(U_FAILURE(*pErrorCode)) { 1.749 + return 0; 1.750 + } 1.751 + if( (src==NULL ? length!=0 : length<-1) || 1.752 + (dest==NULL ? capacity!=0 : capacity<0) || 1.753 + (src==dest && src!=NULL) 1.754 + ) { 1.755 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.756 + return 0; 1.757 + } 1.758 + UnicodeString destString(dest, 0, capacity); 1.759 + // length==0: Nothing to do, and n2wi->normalize(NULL, NULL, buffer, ...) would crash. 1.760 + if(length!=0) { 1.761 + const Normalizer2 *n2=(const Normalizer2 *)norm2; 1.762 + const Normalizer2WithImpl *n2wi=dynamic_cast<const Normalizer2WithImpl *>(n2); 1.763 + if(n2wi!=NULL) { 1.764 + // Avoid duplicate argument checking and support NUL-terminated src. 1.765 + ReorderingBuffer buffer(n2wi->impl, destString); 1.766 + if(buffer.init(length, *pErrorCode)) { 1.767 + n2wi->normalize(src, length>=0 ? src+length : NULL, buffer, *pErrorCode); 1.768 + } 1.769 + } else { 1.770 + UnicodeString srcString(length<0, src, length); 1.771 + n2->normalize(srcString, destString, *pErrorCode); 1.772 + } 1.773 + } 1.774 + return destString.extract(dest, capacity, *pErrorCode); 1.775 +} 1.776 + 1.777 +static int32_t 1.778 +normalizeSecondAndAppend(const UNormalizer2 *norm2, 1.779 + UChar *first, int32_t firstLength, int32_t firstCapacity, 1.780 + const UChar *second, int32_t secondLength, 1.781 + UBool doNormalize, 1.782 + UErrorCode *pErrorCode) { 1.783 + if(U_FAILURE(*pErrorCode)) { 1.784 + return 0; 1.785 + } 1.786 + if( (second==NULL ? secondLength!=0 : secondLength<-1) || 1.787 + (first==NULL ? (firstCapacity!=0 || firstLength!=0) : 1.788 + (firstCapacity<0 || firstLength<-1)) || 1.789 + (first==second && first!=NULL) 1.790 + ) { 1.791 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.792 + return 0; 1.793 + } 1.794 + UnicodeString firstString(first, firstLength, firstCapacity); 1.795 + firstLength=firstString.length(); // In case it was -1. 1.796 + // secondLength==0: Nothing to do, and n2wi->normalizeAndAppend(NULL, NULL, buffer, ...) would crash. 1.797 + if(secondLength!=0) { 1.798 + const Normalizer2 *n2=(const Normalizer2 *)norm2; 1.799 + const Normalizer2WithImpl *n2wi=dynamic_cast<const Normalizer2WithImpl *>(n2); 1.800 + if(n2wi!=NULL) { 1.801 + // Avoid duplicate argument checking and support NUL-terminated src. 1.802 + UnicodeString safeMiddle; 1.803 + { 1.804 + ReorderingBuffer buffer(n2wi->impl, firstString); 1.805 + if(buffer.init(firstLength+secondLength+1, *pErrorCode)) { // destCapacity>=-1 1.806 + n2wi->normalizeAndAppend(second, secondLength>=0 ? second+secondLength : NULL, 1.807 + doNormalize, safeMiddle, buffer, *pErrorCode); 1.808 + } 1.809 + } // The ReorderingBuffer destructor finalizes firstString. 1.810 + if(U_FAILURE(*pErrorCode) || firstString.length()>firstCapacity) { 1.811 + // Restore the modified suffix of the first string. 1.812 + // This does not restore first[] array contents between firstLength and firstCapacity. 1.813 + // (That might be uninitialized memory, as far as we know.) 1.814 + if(first!=NULL) { /* don't dereference NULL */ 1.815 + safeMiddle.extract(0, 0x7fffffff, first+firstLength-safeMiddle.length()); 1.816 + if(firstLength<firstCapacity) { 1.817 + first[firstLength]=0; // NUL-terminate in case it was originally. 1.818 + } 1.819 + } 1.820 + } 1.821 + } else { 1.822 + UnicodeString secondString(secondLength<0, second, secondLength); 1.823 + if(doNormalize) { 1.824 + n2->normalizeSecondAndAppend(firstString, secondString, *pErrorCode); 1.825 + } else { 1.826 + n2->append(firstString, secondString, *pErrorCode); 1.827 + } 1.828 + } 1.829 + } 1.830 + return firstString.extract(first, firstCapacity, *pErrorCode); 1.831 +} 1.832 + 1.833 +U_CAPI int32_t U_EXPORT2 1.834 +unorm2_normalizeSecondAndAppend(const UNormalizer2 *norm2, 1.835 + UChar *first, int32_t firstLength, int32_t firstCapacity, 1.836 + const UChar *second, int32_t secondLength, 1.837 + UErrorCode *pErrorCode) { 1.838 + return normalizeSecondAndAppend(norm2, 1.839 + first, firstLength, firstCapacity, 1.840 + second, secondLength, 1.841 + TRUE, pErrorCode); 1.842 +} 1.843 + 1.844 +U_CAPI int32_t U_EXPORT2 1.845 +unorm2_append(const UNormalizer2 *norm2, 1.846 + UChar *first, int32_t firstLength, int32_t firstCapacity, 1.847 + const UChar *second, int32_t secondLength, 1.848 + UErrorCode *pErrorCode) { 1.849 + return normalizeSecondAndAppend(norm2, 1.850 + first, firstLength, firstCapacity, 1.851 + second, secondLength, 1.852 + FALSE, pErrorCode); 1.853 +} 1.854 + 1.855 +U_CAPI int32_t U_EXPORT2 1.856 +unorm2_getDecomposition(const UNormalizer2 *norm2, 1.857 + UChar32 c, UChar *decomposition, int32_t capacity, 1.858 + UErrorCode *pErrorCode) { 1.859 + if(U_FAILURE(*pErrorCode)) { 1.860 + return 0; 1.861 + } 1.862 + if(decomposition==NULL ? capacity!=0 : capacity<0) { 1.863 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.864 + return 0; 1.865 + } 1.866 + UnicodeString destString(decomposition, 0, capacity); 1.867 + if(reinterpret_cast<const Normalizer2 *>(norm2)->getDecomposition(c, destString)) { 1.868 + return destString.extract(decomposition, capacity, *pErrorCode); 1.869 + } else { 1.870 + return -1; 1.871 + } 1.872 +} 1.873 + 1.874 +U_CAPI int32_t U_EXPORT2 1.875 +unorm2_getRawDecomposition(const UNormalizer2 *norm2, 1.876 + UChar32 c, UChar *decomposition, int32_t capacity, 1.877 + UErrorCode *pErrorCode) { 1.878 + if(U_FAILURE(*pErrorCode)) { 1.879 + return 0; 1.880 + } 1.881 + if(decomposition==NULL ? capacity!=0 : capacity<0) { 1.882 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.883 + return 0; 1.884 + } 1.885 + UnicodeString destString(decomposition, 0, capacity); 1.886 + if(reinterpret_cast<const Normalizer2 *>(norm2)->getRawDecomposition(c, destString)) { 1.887 + return destString.extract(decomposition, capacity, *pErrorCode); 1.888 + } else { 1.889 + return -1; 1.890 + } 1.891 +} 1.892 + 1.893 +U_CAPI UChar32 U_EXPORT2 1.894 +unorm2_composePair(const UNormalizer2 *norm2, UChar32 a, UChar32 b) { 1.895 + return reinterpret_cast<const Normalizer2 *>(norm2)->composePair(a, b); 1.896 +} 1.897 + 1.898 +U_CAPI uint8_t U_EXPORT2 1.899 +unorm2_getCombiningClass(const UNormalizer2 *norm2, UChar32 c) { 1.900 + return reinterpret_cast<const Normalizer2 *>(norm2)->getCombiningClass(c); 1.901 +} 1.902 + 1.903 +U_CAPI UBool U_EXPORT2 1.904 +unorm2_isNormalized(const UNormalizer2 *norm2, 1.905 + const UChar *s, int32_t length, 1.906 + UErrorCode *pErrorCode) { 1.907 + if(U_FAILURE(*pErrorCode)) { 1.908 + return 0; 1.909 + } 1.910 + if((s==NULL && length!=0) || length<-1) { 1.911 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.912 + return 0; 1.913 + } 1.914 + UnicodeString sString(length<0, s, length); 1.915 + return ((const Normalizer2 *)norm2)->isNormalized(sString, *pErrorCode); 1.916 +} 1.917 + 1.918 +U_CAPI UNormalizationCheckResult U_EXPORT2 1.919 +unorm2_quickCheck(const UNormalizer2 *norm2, 1.920 + const UChar *s, int32_t length, 1.921 + UErrorCode *pErrorCode) { 1.922 + if(U_FAILURE(*pErrorCode)) { 1.923 + return UNORM_NO; 1.924 + } 1.925 + if((s==NULL && length!=0) || length<-1) { 1.926 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.927 + return UNORM_NO; 1.928 + } 1.929 + UnicodeString sString(length<0, s, length); 1.930 + return ((const Normalizer2 *)norm2)->quickCheck(sString, *pErrorCode); 1.931 +} 1.932 + 1.933 +U_CAPI int32_t U_EXPORT2 1.934 +unorm2_spanQuickCheckYes(const UNormalizer2 *norm2, 1.935 + const UChar *s, int32_t length, 1.936 + UErrorCode *pErrorCode) { 1.937 + if(U_FAILURE(*pErrorCode)) { 1.938 + return 0; 1.939 + } 1.940 + if((s==NULL && length!=0) || length<-1) { 1.941 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.942 + return 0; 1.943 + } 1.944 + UnicodeString sString(length<0, s, length); 1.945 + return ((const Normalizer2 *)norm2)->spanQuickCheckYes(sString, *pErrorCode); 1.946 +} 1.947 + 1.948 +U_CAPI UBool U_EXPORT2 1.949 +unorm2_hasBoundaryBefore(const UNormalizer2 *norm2, UChar32 c) { 1.950 + return ((const Normalizer2 *)norm2)->hasBoundaryBefore(c); 1.951 +} 1.952 + 1.953 +U_CAPI UBool U_EXPORT2 1.954 +unorm2_hasBoundaryAfter(const UNormalizer2 *norm2, UChar32 c) { 1.955 + return ((const Normalizer2 *)norm2)->hasBoundaryAfter(c); 1.956 +} 1.957 + 1.958 +U_CAPI UBool U_EXPORT2 1.959 +unorm2_isInert(const UNormalizer2 *norm2, UChar32 c) { 1.960 + return ((const Normalizer2 *)norm2)->isInert(c); 1.961 +} 1.962 + 1.963 +// Some properties APIs ---------------------------------------------------- *** 1.964 + 1.965 +U_CAPI uint8_t U_EXPORT2 1.966 +u_getCombiningClass(UChar32 c) { 1.967 + UErrorCode errorCode=U_ZERO_ERROR; 1.968 + const Normalizer2 *nfd=Normalizer2Factory::getNFDInstance(errorCode); 1.969 + if(U_SUCCESS(errorCode)) { 1.970 + return nfd->getCombiningClass(c); 1.971 + } else { 1.972 + return 0; 1.973 + } 1.974 +} 1.975 + 1.976 +U_CFUNC UNormalizationCheckResult 1.977 +unorm_getQuickCheck(UChar32 c, UNormalizationMode mode) { 1.978 + if(mode<=UNORM_NONE || UNORM_FCD<=mode) { 1.979 + return UNORM_YES; 1.980 + } 1.981 + UErrorCode errorCode=U_ZERO_ERROR; 1.982 + const Normalizer2 *norm2=Normalizer2Factory::getInstance(mode, errorCode); 1.983 + if(U_SUCCESS(errorCode)) { 1.984 + return ((const Normalizer2WithImpl *)norm2)->getQuickCheck(c); 1.985 + } else { 1.986 + return UNORM_MAYBE; 1.987 + } 1.988 +} 1.989 + 1.990 +U_CFUNC uint16_t 1.991 +unorm_getFCD16(UChar32 c) { 1.992 + UErrorCode errorCode=U_ZERO_ERROR; 1.993 + const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(errorCode); 1.994 + if(U_SUCCESS(errorCode)) { 1.995 + return impl->getFCD16(c); 1.996 + } else { 1.997 + return 0; 1.998 + } 1.999 +} 1.1000 + 1.1001 +#endif // !UCONFIG_NO_NORMALIZATION