-class FCDTrieSingleton : public UTrie2Singleton {
-public:
- FCDTrieSingleton(SimpleSingleton &s, Normalizer2Impl &ni, UErrorCode &ec) :
- UTrie2Singleton(s), impl(ni), errorCode(ec) {}
- UTrie2 *getInstance(UErrorCode &errorCode) {
- return UTrie2Singleton::getInstance(createInstance, this, errorCode);
- }
- static void *createInstance(const void *context, UErrorCode &errorCode);
- UBool rangeHandler(UChar32 start, UChar32 end, uint32_t value) {
- if(value!=0) {
- impl.setFCD16FromNorm16(start, end, (uint16_t)value, newFCDTrie, errorCode);
- }
- return U_SUCCESS(errorCode);
- }
-
- Normalizer2Impl &impl;
- UTrie2 *newFCDTrie;
- UErrorCode &errorCode;
-};
-
-U_CDECL_BEGIN
-
-// Set the FCD value for a range of same-norm16 characters.
-static UBool U_CALLCONV
-enumRangeHandler(const void *context, UChar32 start, UChar32 end, uint32_t value) {
- return ((FCDTrieSingleton *)context)->rangeHandler(start, end, value);
-}
-
-// Collect (OR together) the FCD values for a range of supplementary characters,
-// for their lead surrogate code unit.
-static UBool U_CALLCONV
-enumRangeOrValue(const void *context, UChar32 /*start*/, UChar32 /*end*/, uint32_t value) {
- *((uint32_t *)context)|=value;
- return TRUE;
-}
-
-U_CDECL_END
-
-void *FCDTrieSingleton::createInstance(const void *context, UErrorCode &errorCode) {
- FCDTrieSingleton *me=(FCDTrieSingleton *)context;
- me->newFCDTrie=utrie2_open(0, 0, &errorCode);
- if(U_SUCCESS(errorCode)) {
- utrie2_enum(me->impl.getNormTrie(), NULL, enumRangeHandler, me);
- for(UChar lead=0xd800; lead<0xdc00; ++lead) {
- uint32_t oredValue=utrie2_get32(me->newFCDTrie, lead);
- utrie2_enumForLeadSurrogate(me->newFCDTrie, lead, NULL, enumRangeOrValue, &oredValue);
- if(oredValue!=0) {
- // Set a "bad" value for makeFCD() to break the quick check loop
- // and look up the value for the supplementary code point.
- // If there is any lccc, then set the worst-case lccc of 1.
- // The ORed-together value's tccc is already the worst case.
- if(oredValue>0xff) {
- oredValue=0x100|(oredValue&0xff);
- }
- utrie2_set32ForLeadSurrogateCodeUnit(me->newFCDTrie, lead, oredValue, &errorCode);
- }
- }
- utrie2_freeze(me->newFCDTrie, UTRIE2_16_VALUE_BITS, &errorCode);
- if(U_SUCCESS(errorCode)) {
- return me->newFCDTrie;
- }
- }
- utrie2_close(me->newFCDTrie);
- return NULL;
-}