2 ******************************************************************************
3 * Copyright (C) 1996-2011, International Business Machines *
4 * Corporation and others. All Rights Reserved. *
5 ******************************************************************************
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_COLLATION
12 #include "unicode/unistr.h"
13 #include "unicode/putil.h"
14 #include "unicode/usearch.h"
17 #include "unicode/coll.h"
18 #include "unicode/tblcoll.h"
19 #include "unicode/coleitr.h"
20 #include "unicode/ucoleitr.h"
22 #include "unicode/regex.h" // TODO: make conditional on regexp being built.
24 #include "unicode/uniset.h"
25 #include "unicode/uset.h"
26 #include "unicode/ustring.h"
34 #include "unicode/colldata.h"
38 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
39 #define NEW_ARRAY(type, count) (type *) uprv_malloc((count) * sizeof(type))
40 #define DELETE_ARRAY(array) uprv_free((void *) (array))
41 #define ARRAY_COPY(dst, src, count) uprv_memcpy((void *) (dst), (void *) (src), (count) * sizeof (src)[0])
43 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CEList
)
45 #ifdef INSTRUMENT_CELIST
46 int32_t CEList::_active
= 0;
47 int32_t CEList::_histogram
[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
50 CEList::CEList(UCollator
*coll
, const UnicodeString
&string
, UErrorCode
&status
)
51 : ces(NULL
), listMax(CELIST_BUFFER_SIZE
), listSize(0)
53 UCollationElements
*elems
= ucol_openElements(coll
, string
.getBuffer(), string
.length(), &status
);
54 UCollationStrength strength
= ucol_getStrength(coll
);
55 UBool toShift
= ucol_getAttribute(coll
, UCOL_ALTERNATE_HANDLING
, &status
) == UCOL_SHIFTED
;
56 uint32_t variableTop
= ucol_getVariableTop(coll
, &status
);
57 uint32_t strengthMask
= 0;
60 if (U_FAILURE(status
)) {
64 // **** only set flag if string has Han(gul) ****
65 ucol_forceHanImplicit(elems
, &status
);
70 strengthMask
|= UCOL_TERTIARYORDERMASK
;
74 strengthMask
|= UCOL_SECONDARYORDERMASK
;
78 strengthMask
|= UCOL_PRIMARYORDERMASK
;
81 #ifdef INSTRUMENT_CELIST
88 while ((order
= ucol_next(elems
, &status
)) != UCOL_NULLORDER
) {
89 UBool cont
= isContinuation(order
);
91 order
&= strengthMask
;
93 if (toShift
&& variableTop
> (uint32_t)order
&& (order
& UCOL_PRIMARYORDERMASK
) != 0) {
94 if (strength
>= UCOL_QUATERNARY
) {
95 order
&= UCOL_PRIMARYORDERMASK
;
97 order
= UCOL_IGNORABLE
;
101 if (order
== UCOL_IGNORABLE
) {
106 order
|= UCOL_CONTINUATION_MARKER
;
112 ucol_closeElements(elems
);
117 #ifdef INSTRUMENT_CELIST
121 if (ces
!= ceBuffer
) {
126 void CEList::add(uint32_t ce
, UErrorCode
&status
)
128 if (U_FAILURE(status
)) {
132 if (listSize
>= listMax
) {
133 int32_t newMax
= listMax
+ CELIST_BUFFER_SIZE
;
135 #ifdef INSTRUMENT_CELIST
136 _histogram
[listSize
/ CELIST_BUFFER_SIZE
] += 1;
139 uint32_t *newCEs
= NEW_ARRAY(uint32_t, newMax
);
141 if (newCEs
== NULL
) {
142 status
= U_MEMORY_ALLOCATION_ERROR
;
146 uprv_memcpy(newCEs
, ces
, listSize
* sizeof(uint32_t));
148 if (ces
!= ceBuffer
) {
156 ces
[listSize
++] = ce
;
159 uint32_t CEList::get(int32_t index
) const
161 if (index
>= 0 && index
< listSize
) {
165 return UCOL_NULLORDER
;
168 uint32_t &CEList::operator[](int32_t index
) const
173 UBool
CEList::matchesAt(int32_t offset
, const CEList
*other
) const
175 if (other
== NULL
|| listSize
- offset
< other
->size()) {
179 for (int32_t i
= offset
, j
= 0; j
< other
->size(); i
+= 1, j
+= 1) {
180 if (ces
[i
] != (*other
)[j
]) {
188 int32_t CEList::size() const
193 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringList
)
195 #ifdef INSTRUMENT_STRING_LIST
196 int32_t StringList::_lists
= 0;
197 int32_t StringList::_strings
= 0;
198 int32_t StringList::_histogram
[101] = {0};
201 StringList::StringList(UErrorCode
&status
)
202 : strings(NULL
), listMax(STRING_LIST_BUFFER_SIZE
), listSize(0)
204 if (U_FAILURE(status
)) {
208 strings
= new UnicodeString
[listMax
];
210 if (strings
== NULL
) {
211 status
= U_MEMORY_ALLOCATION_ERROR
;
215 #ifdef INSTRUMENT_STRING_LIST
221 StringList::~StringList()
226 void StringList::add(const UnicodeString
*string
, UErrorCode
&status
)
228 if (U_FAILURE(status
)) {
232 #ifdef INSTRUMENT_STRING_LIST
236 if (listSize
>= listMax
) {
237 int32_t newMax
= listMax
+ STRING_LIST_BUFFER_SIZE
;
238 UnicodeString
*newStrings
= new UnicodeString
[newMax
];
239 if (newStrings
== NULL
) {
240 status
= U_MEMORY_ALLOCATION_ERROR
;
243 for (int32_t i
=0; i
<listSize
; ++i
) {
244 newStrings
[i
] = strings
[i
];
247 #ifdef INSTRUMENT_STRING_LIST
248 int32_t _h
= listSize
/ STRING_LIST_BUFFER_SIZE
;
258 strings
= newStrings
;
262 // The ctor initialized all the strings in
263 // the array to empty strings, so this
264 // is the same as copying the source string.
265 strings
[listSize
++].append(*string
);
268 void StringList::add(const UChar
*chars
, int32_t count
, UErrorCode
&status
)
270 const UnicodeString
string(chars
, count
);
272 add(&string
, status
);
275 const UnicodeString
*StringList::get(int32_t index
) const
277 if (index
>= 0 && index
< listSize
) {
278 return &strings
[index
];
284 int32_t StringList::size() const
290 U_CFUNC
void deleteStringList(void *obj
);
292 class CEToStringsMap
: public UMemory
296 CEToStringsMap(UErrorCode
&status
);
299 void put(uint32_t ce
, UnicodeString
*string
, UErrorCode
&status
);
300 StringList
*getStringList(uint32_t ce
) const;
304 void putStringList(uint32_t ce
, StringList
*stringList
, UErrorCode
&status
);
308 CEToStringsMap::CEToStringsMap(UErrorCode
&status
)
311 if (U_FAILURE(status
)) {
315 map
= uhash_open(uhash_hashLong
, uhash_compareLong
,
316 uhash_compareCaselessUnicodeString
,
319 if (U_FAILURE(status
)) {
323 uhash_setValueDeleter(map
, deleteStringList
);
326 CEToStringsMap::~CEToStringsMap()
331 void CEToStringsMap::put(uint32_t ce
, UnicodeString
*string
, UErrorCode
&status
)
333 StringList
*strings
= getStringList(ce
);
335 if (strings
== NULL
) {
336 strings
= new StringList(status
);
338 if (strings
== NULL
|| U_FAILURE(status
)) {
339 status
= U_MEMORY_ALLOCATION_ERROR
;
343 putStringList(ce
, strings
, status
);
346 strings
->add(string
, status
);
349 StringList
*CEToStringsMap::getStringList(uint32_t ce
) const
351 return (StringList
*) uhash_iget(map
, ce
);
354 void CEToStringsMap::putStringList(uint32_t ce
, StringList
*stringList
, UErrorCode
&status
)
356 uhash_iput(map
, ce
, (void *) stringList
, &status
);
359 U_CFUNC
void deleteStringList(void *obj
)
361 StringList
*strings
= (StringList
*) obj
;
366 U_CFUNC
void deleteCEList(void *obj
);
367 U_CFUNC
void deleteUnicodeStringKey(void *obj
);
369 class StringToCEsMap
: public UMemory
372 StringToCEsMap(UErrorCode
&status
);
375 void put(const UnicodeString
*string
, const CEList
*ces
, UErrorCode
&status
);
376 const CEList
*get(const UnicodeString
*string
);
377 void free(const CEList
*list
);
385 StringToCEsMap::StringToCEsMap(UErrorCode
&status
)
388 if (U_FAILURE(status
)) {
392 map
= uhash_open(uhash_hashUnicodeString
,
393 uhash_compareUnicodeString
,
397 if (U_FAILURE(status
)) {
401 uhash_setValueDeleter(map
, deleteCEList
);
402 uhash_setKeyDeleter(map
, deleteUnicodeStringKey
);
405 StringToCEsMap::~StringToCEsMap()
410 void StringToCEsMap::put(const UnicodeString
*string
, const CEList
*ces
, UErrorCode
&status
)
412 uhash_put(map
, (void *) string
, (void *) ces
, &status
);
415 const CEList
*StringToCEsMap::get(const UnicodeString
*string
)
417 return (const CEList
*) uhash_get(map
, string
);
420 U_CFUNC
void deleteCEList(void *obj
)
422 CEList
*list
= (CEList
*) obj
;
427 U_CFUNC
void deleteUnicodeStringKey(void *obj
)
429 UnicodeString
*key
= (UnicodeString
*) obj
;
434 class CollDataCacheEntry
: public UMemory
437 CollDataCacheEntry(CollData
*theData
);
438 ~CollDataCacheEntry();
444 CollDataCacheEntry::CollDataCacheEntry(CollData
*theData
)
445 : data(theData
), refCount(1)
447 // nothing else to do
450 CollDataCacheEntry::~CollDataCacheEntry()
456 class CollDataCache
: public UMemory
459 CollDataCache(UErrorCode
&status
);
462 CollData
*get(UCollator
*collator
, UErrorCode
&status
);
463 void unref(CollData
*collData
);
468 static char *getKey(UCollator
*collator
, char *keyBuffer
, int32_t *charBufferLength
);
469 static void deleteKey(char *key
);
475 U_CFUNC
void deleteChars(void * /*obj*/)
477 // char *chars = (char *) obj;
478 // All the key strings are owned by the
479 // CollData objects and don't need to
481 //DELETE_ARRAY(chars);
484 U_CFUNC
void deleteCollDataCacheEntry(void *obj
)
486 CollDataCacheEntry
*entry
= (CollDataCacheEntry
*) obj
;
491 CollDataCache::CollDataCache(UErrorCode
&status
)
494 if (U_FAILURE(status
)) {
498 cache
= uhash_open(uhash_hashChars
, uhash_compareChars
, uhash_compareLong
, &status
);
500 if (U_FAILURE(status
)) {
504 uhash_setValueDeleter(cache
, deleteCollDataCacheEntry
);
505 uhash_setKeyDeleter(cache
, deleteChars
);
508 CollDataCache::~CollDataCache()
516 CollData
*CollDataCache::get(UCollator
*collator
, UErrorCode
&status
)
518 char keyBuffer
[KEY_BUFFER_SIZE
];
519 int32_t keyLength
= KEY_BUFFER_SIZE
;
520 char *key
= getKey(collator
, keyBuffer
, &keyLength
);
521 CollData
*result
= NULL
, *newData
= NULL
;
522 CollDataCacheEntry
*entry
= NULL
, *newEntry
= NULL
;
525 entry
= (CollDataCacheEntry
*) uhash_get(cache
, key
);
530 newData
= new CollData(collator
, key
, keyLength
, status
);
531 newEntry
= new CollDataCacheEntry(newData
);
533 if (U_FAILURE(status
) || newData
== NULL
|| newEntry
== NULL
) {
534 status
= U_MEMORY_ALLOCATION_ERROR
;
539 entry
= (CollDataCacheEntry
*) uhash_get(cache
, key
);
542 uhash_put(cache
, newData
->key
, newEntry
, &status
);
545 if (U_FAILURE(status
)) {
556 result
= entry
->data
;
557 entry
->refCount
+= 1;
560 if (key
!= keyBuffer
) {
564 if (newEntry
!= NULL
) {
572 void CollDataCache::unref(CollData
*collData
)
574 CollDataCacheEntry
*entry
= NULL
;
577 entry
= (CollDataCacheEntry
*) uhash_get(cache
, collData
->key
);
580 entry
->refCount
-= 1;
585 char *CollDataCache::getKey(UCollator
*collator
, char *keyBuffer
, int32_t *keyBufferLength
)
587 UErrorCode status
= U_ZERO_ERROR
;
588 int32_t len
= ucol_getShortDefinitionString(collator
, NULL
, keyBuffer
, *keyBufferLength
, &status
);
590 if (len
>= *keyBufferLength
) {
591 *keyBufferLength
= (len
+ 2) & ~1; // round to even length, leaving room for terminating null
592 keyBuffer
= NEW_ARRAY(char, *keyBufferLength
);
593 status
= U_ZERO_ERROR
;
595 len
= ucol_getShortDefinitionString(collator
, NULL
, keyBuffer
, *keyBufferLength
, &status
);
598 keyBuffer
[len
] = '\0';
603 void CollDataCache::flush()
605 const UHashElement
*element
;
609 while ((element
= uhash_nextElement(cache
, &pos
)) != NULL
) {
610 CollDataCacheEntry
*entry
= (CollDataCacheEntry
*) element
->value
.pointer
;
612 if (entry
->refCount
<= 0) {
613 uhash_removeElement(cache
, element
);
619 void CollDataCache::deleteKey(char *key
)
625 static UBool
coll_data_cleanup(void) {
626 CollData::freeCollDataCache();
631 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollData
)
638 #define CLONE_COLLATOR
640 //#define CACHE_CELISTS
641 CollData::CollData(UCollator
*collator
, char *cacheKey
, int32_t cacheKeyLength
, UErrorCode
&status
)
642 : coll(NULL
), charsToCEList(NULL
), ceToCharsStartingWith(NULL
), key(NULL
)
644 // [:c:] == [[:cn:][:cc:][:co:][:cf:][:cs:]]
645 // i.e. other, control, private use, format, surrogate
646 U_STRING_DECL(test_pattern
, "[[:assigned:]-[:c:]]", 20);
647 U_STRING_INIT(test_pattern
, "[[:assigned:]-[:c:]]", 20);
648 USet
*charsToTest
= uset_openPattern(test_pattern
, 20, &status
);
650 // Han ext. A, Han, Jamo, Hangul, Han Ext. B
651 // i.e. all the characers we handle implicitly
652 U_STRING_DECL(remove_pattern
, "[[\\u3400-\\u9FFF][\\u1100-\\u11F9][\\uAC00-\\uD7AF][\\U00020000-\\U0002A6DF]]", 70);
653 U_STRING_INIT(remove_pattern
, "[[\\u3400-\\u9FFF][\\u1100-\\u11F9][\\uAC00-\\uD7AF][\\U00020000-\\U0002A6DF]]", 70);
654 USet
*charsToRemove
= uset_openPattern(remove_pattern
, 70, &status
);
656 if (U_FAILURE(status
)) {
660 USet
*expansions
= uset_openEmpty();
661 USet
*contractions
= uset_openEmpty();
665 charsToCEList
= new StringToCEsMap(status
);
667 if (U_FAILURE(status
)) {
671 charsToCEList
= NULL
;
674 ceToCharsStartingWith
= new CEToStringsMap(status
);
676 if (U_FAILURE(status
)) {
680 if (cacheKeyLength
> KEY_BUFFER_SIZE
) {
681 key
= NEW_ARRAY(char, cacheKeyLength
);
684 status
= U_MEMORY_ALLOCATION_ERROR
;
691 ARRAY_COPY(key
, cacheKey
, cacheKeyLength
);
693 #ifdef CLONE_COLLATOR
694 coll
= ucol_safeClone(collator
, NULL
, NULL
, &status
);
696 if (U_FAILURE(status
)) {
703 ucol_getContractionsAndExpansions(coll
, contractions
, expansions
, FALSE
, &status
);
705 uset_addAll(charsToTest
, contractions
);
706 uset_addAll(charsToTest
, expansions
);
707 uset_removeAll(charsToTest
, charsToRemove
);
709 itemCount
= uset_getItemCount(charsToTest
);
710 for(int32_t item
= 0; item
< itemCount
; item
+= 1) {
711 UChar32 start
= 0, end
= 0;
713 int32_t len
= uset_getItem(charsToTest
, item
, &start
, &end
,
714 buffer
, 16, &status
);
717 for (UChar32 ch
= start
; ch
<= end
; ch
+= 1) {
718 UnicodeString
*st
= new UnicodeString(ch
);
721 status
= U_MEMORY_ALLOCATION_ERROR
;
725 CEList
*ceList
= new CEList(coll
, *st
, status
);
727 ceToCharsStartingWith
->put(ceList
->get(0), st
, status
);
730 charsToCEList
->put(st
, ceList
, status
);
736 } else if (len
> 0) {
737 UnicodeString
*st
= new UnicodeString(buffer
, len
);
740 status
= U_MEMORY_ALLOCATION_ERROR
;
744 CEList
*ceList
= new CEList(coll
, *st
, status
);
746 ceToCharsStartingWith
->put(ceList
->get(0), st
, status
);
749 charsToCEList
->put(st
, ceList
, status
);
755 // shouldn't happen...
758 if (U_FAILURE(status
)) {
764 uset_close(contractions
);
765 uset_close(expansions
);
766 uset_close(charsToRemove
);
767 uset_close(charsToTest
);
769 if (U_FAILURE(status
)) {
773 UChar32 hanRanges
[] = {UCOL_FIRST_HAN
, UCOL_LAST_HAN
, UCOL_FIRST_HAN_COMPAT
, UCOL_LAST_HAN_COMPAT
, UCOL_FIRST_HAN_A
, UCOL_LAST_HAN_A
,
774 UCOL_FIRST_HAN_B
, UCOL_LAST_HAN_B
};
775 UChar jamoRanges
[] = {UCOL_FIRST_L_JAMO
, UCOL_FIRST_V_JAMO
, UCOL_FIRST_T_JAMO
, UCOL_LAST_T_JAMO
};
776 UnicodeString hanString
= UnicodeString::fromUTF32(hanRanges
, ARRAY_SIZE(hanRanges
));
777 UnicodeString
jamoString(FALSE
, jamoRanges
, ARRAY_SIZE(jamoRanges
));
778 CEList
hanList(coll
, hanString
, status
);
779 CEList
jamoList(coll
, jamoString
, status
);
782 if (U_FAILURE(status
)) {
786 for (int32_t c
= 0; c
< jamoList
.size(); c
+= 1) {
787 uint32_t jce
= jamoList
[c
];
789 if (! isContinuation(jce
)) {
790 jamoLimits
[j
++] = jce
;
794 jamoLimits
[3] += (1 << UCOL_PRIMARYORDERSHIFT
);
799 for(int32_t h
= 0; h
< hanList
.size(); h
+= 2) {
800 uint32_t han
= (uint32_t) hanList
[h
];
811 maxHan
+= (1 << UCOL_PRIMARYORDERSHIFT
);
814 CollData::~CollData()
816 #ifdef CLONE_COLLATOR
820 if (key
!= keyBuffer
) {
824 delete ceToCharsStartingWith
;
827 delete charsToCEList
;
831 UCollator
*CollData::getCollator() const
836 const StringList
*CollData::getStringList(int32_t ce
) const
838 return ceToCharsStartingWith
->getStringList(ce
);
841 const CEList
*CollData::getCEList(const UnicodeString
*string
) const
844 return charsToCEList
->get(string
);
846 UErrorCode status
= U_ZERO_ERROR
;
847 const CEList
*list
= new CEList(coll
, *string
, status
);
849 if (U_FAILURE(status
)) {
858 void CollData::freeCEList(const CEList
*list
)
860 #ifndef CACHE_CELISTS
865 int32_t CollData::minLengthInChars(const CEList
*ceList
, int32_t offset
, int32_t *history
) const
867 // find out shortest string for the longest sequence of ces.
868 // this can probably be folded with the minLengthCache...
870 if (history
[offset
] >= 0) {
871 return history
[offset
];
874 uint32_t ce
= ceList
->get(offset
);
875 int32_t maxOffset
= ceList
->size();
876 int32_t shortestLength
= INT32_MAX
;
877 const StringList
*strings
= ceToCharsStartingWith
->getStringList(ce
);
879 if (strings
!= NULL
) {
880 int32_t stringCount
= strings
->size();
882 for (int32_t s
= 0; s
< stringCount
; s
+= 1) {
883 const UnicodeString
*string
= strings
->get(s
);
885 const CEList
*ceList2
= charsToCEList
->get(string
);
887 UErrorCode status
= U_ZERO_ERROR
;
888 const CEList
*ceList2
= new CEList(coll
, *string
, status
);
890 if (U_FAILURE(status
)) {
896 if (ceList
->matchesAt(offset
, ceList2
)) {
897 U_ASSERT(ceList2
!= NULL
);
898 int32_t clength
= ceList2
->size();
899 int32_t slength
= string
->length();
900 int32_t roffset
= offset
+ clength
;
903 if (roffset
< maxOffset
) {
904 rlength
= minLengthInChars(ceList
, roffset
, history
);
907 // delete before continue to avoid memory leak.
908 #ifndef CACHE_CELISTS
911 // ignore any dead ends
916 if (shortestLength
> slength
+ rlength
) {
917 shortestLength
= slength
+ rlength
;
921 #ifndef CACHE_CELISTS
927 if (shortestLength
== INT32_MAX
) {
928 // No matching strings at this offset. See if
929 // the CE is in a range we can handle manually.
930 if (ce
>= minHan
&& ce
< maxHan
) {
931 // all han have implicit orders which
933 int32_t roffset
= offset
+ 2;
936 //history[roffset++] = -1;
937 //history[roffset++] = 1;
939 if (roffset
< maxOffset
) {
940 rlength
= minLengthInChars(ceList
, roffset
, history
);
947 shortestLength
= 1 + rlength
;
949 } else if (ce
>= jamoLimits
[0] && ce
< jamoLimits
[3]) {
950 int32_t roffset
= offset
;
953 // **** this loop may not handle archaic Hangul correctly ****
954 for (int32_t j
= 0; roffset
< maxOffset
&& j
< 4; j
+= 1, roffset
+= 1) {
955 uint32_t jce
= ceList
->get(roffset
);
957 // Some Jamo have 24-bit primary order; skip the
958 // 2nd CE. This should always be OK because if
959 // we're still in the loop all we've seen are
960 // a series of Jamo in LVT order.
961 if (isContinuation(jce
)) {
965 if (j
>= 3 || jce
< jamoLimits
[j
] || jce
>= jamoLimits
[j
+ 1]) {
970 if (roffset
== offset
) {
971 // we started with a non-L Jamo...
972 // just say it comes from a single character
975 // See if the single Jamo has a 24-bit order.
976 if (roffset
< maxOffset
&& isContinuation(ceList
->get(roffset
))) {
981 if (roffset
< maxOffset
) {
982 rlength
= minLengthInChars(ceList
, roffset
, history
);
989 shortestLength
= 1 + rlength
;
993 // Can't handle it manually either. Just move on.
998 history
[offset
] = shortestLength
;
1000 return shortestLength
;
1003 int32_t CollData::minLengthInChars(const CEList
*ceList
, int32_t offset
) const
1005 int32_t clength
= ceList
->size();
1006 int32_t *history
= NEW_ARRAY(int32_t, clength
);
1008 for (int32_t i
= 0; i
< clength
; i
+= 1) {
1012 int32_t minLength
= minLengthInChars(ceList
, offset
, history
);
1014 DELETE_ARRAY(history
);
1019 CollData
*CollData::open(UCollator
*collator
, UErrorCode
&status
)
1021 if (U_FAILURE(status
)) {
1025 CollDataCache
*cache
= getCollDataCache();
1027 return cache
->get(collator
, status
);
1030 void CollData::close(CollData
*collData
)
1032 CollDataCache
*cache
= getCollDataCache();
1034 cache
->unref(collData
);
1037 CollDataCache
*CollData::collDataCache
= NULL
;
1039 CollDataCache
*CollData::getCollDataCache()
1041 UErrorCode status
= U_ZERO_ERROR
;
1042 CollDataCache
*cache
= NULL
;
1044 UMTX_CHECK(NULL
, collDataCache
, cache
);
1046 if (cache
== NULL
) {
1047 cache
= new CollDataCache(status
);
1049 if (U_FAILURE(status
)) {
1055 if (collDataCache
== NULL
) {
1056 collDataCache
= cache
;
1058 ucln_i18n_registerCleanup(UCLN_I18N_COLL_DATA
, coll_data_cleanup
);
1062 if (collDataCache
!= cache
) {
1067 return collDataCache
;
1070 void CollData::freeCollDataCache()
1072 CollDataCache
*cache
= NULL
;
1074 UMTX_CHECK(NULL
, collDataCache
, cache
);
1076 if (cache
!= NULL
) {
1078 if (collDataCache
!= NULL
) {
1079 collDataCache
= NULL
;
1089 void CollData::flushCollDataCache()
1091 CollDataCache
*cache
= NULL
;
1093 UMTX_CHECK(NULL
, collDataCache
, cache
);
1095 // **** this will fail if the another ****
1096 // **** thread deletes the cache here ****
1097 if (cache
!= NULL
) {
1104 #endif // #if !UCONFIG_NO_COLLATION