2323#include " umutex.h"
2424#include " uprops.h"
2525
26+ using icu::LocalPointer;
27+ #if !UCONFIG_NO_NORMALIZATION
28+ using icu::Normalizer2Factory;
29+ using icu::Normalizer2Impl;
30+ #endif
2631using icu::UInitOnce;
2732using icu::UnicodeSet;
2833
2934namespace {
3035
3136UBool U_CALLCONV characterproperties_cleanup ();
3237
38+ constexpr int32_t NUM_INCLUSIONS = UPROPS_SRC_COUNT + UCHAR_INT_LIMIT - UCHAR_INT_START;
39+
3340struct Inclusion {
3441 UnicodeSet *fSet ;
3542 UInitOnce fInitOnce ;
3643};
37- Inclusion gInclusions [UPROPS_SRC_COUNT ]; // cached getInclusions()
44+ Inclusion gInclusions [NUM_INCLUSIONS ]; // cached getInclusions()
3845
3946UnicodeSet *sets[UCHAR_BINARY_LIMIT] = {};
4047
4148UCPMap *maps[UCHAR_INT_LIMIT - UCHAR_INT_START] = {};
4249
43- UMutex cpMutex = U_MUTEX_INITIALIZER;
50+ icu::UMutex *cpMutex () {
51+ static icu::UMutex m = U_MUTEX_INITIALIZER;
52+ return &m;
53+ }
4454
4555// ----------------------------------------------------------------
4656// Inclusions list
@@ -80,43 +90,29 @@ UBool U_CALLCONV characterproperties_cleanup() {
8090 return TRUE ;
8191}
8292
83- } // namespace
84-
85- U_NAMESPACE_BEGIN
86-
87- /*
88- Reduce excessive reallocation, and make it easier to detect initialization problems.
89- Usually you don't see smaller sets than this for Unicode 5.0.
90- */
91- constexpr int32_t DEFAULT_INCLUSION_CAPACITY = 3072 ;
92-
93- void U_CALLCONV CharacterProperties::initInclusion (UPropertySource src, UErrorCode &errorCode) {
93+ void U_CALLCONV initInclusion (UPropertySource src, UErrorCode &errorCode) {
9494 // This function is invoked only via umtx_initOnce().
95- // This function is a friend of class UnicodeSet.
96-
9795 U_ASSERT (0 <= src && src < UPROPS_SRC_COUNT);
9896 if (src == UPROPS_SRC_NONE) {
9997 errorCode = U_INTERNAL_PROGRAM_ERROR;
10098 return ;
10199 }
102- UnicodeSet * &incl = gInclusions [src].fSet ;
103- U_ASSERT (incl == nullptr );
100+ U_ASSERT (gInclusions [src].fSet == nullptr );
104101
105- incl = new UnicodeSet ();
106- if (incl == nullptr ) {
102+ LocalPointer<UnicodeSet> incl ( new UnicodeSet () );
103+ if (incl. isNull () ) {
107104 errorCode = U_MEMORY_ALLOCATION_ERROR;
108105 return ;
109106 }
110107 USetAdder sa = {
111- (USet *)incl,
108+ (USet *)incl. getAlias () ,
112109 _set_add,
113110 _set_addRange,
114111 _set_addString,
115112 nullptr , // don't need remove()
116113 nullptr // don't need removeRange()
117114 };
118115
119- incl->ensureCapacity (DEFAULT_INCLUSION_CAPACITY, errorCode);
120116 switch (src) {
121117 case UPROPS_SRC_CHAR:
122118 uchar_addPropertyStarts (&sa, &errorCode);
@@ -183,12 +179,15 @@ void U_CALLCONV CharacterProperties::initInclusion(UPropertySource src, UErrorCo
183179 }
184180
185181 if (U_FAILURE (errorCode)) {
186- delete incl;
187- incl = nullptr ;
188182 return ;
189183 }
190- // Compact for caching
184+ if (incl->isBogus ()) {
185+ errorCode = U_MEMORY_ALLOCATION_ERROR;
186+ return ;
187+ }
188+ // Compact for caching.
191189 incl->compact ();
190+ gInclusions [src].fSet = incl.orphan ();
192191 ucln_common_registerCleanup (UCLN_COMMON_CHARACTERPROPERTIES, characterproperties_cleanup);
193192}
194193
@@ -199,15 +198,66 @@ const UnicodeSet *getInclusionsForSource(UPropertySource src, UErrorCode &errorC
199198 return nullptr ;
200199 }
201200 Inclusion &i = gInclusions [src];
202- umtx_initOnce (i.fInitOnce , &CharacterProperties:: initInclusion, src, errorCode);
201+ umtx_initOnce (i.fInitOnce , &initInclusion, src, errorCode);
203202 return i.fSet ;
204203}
205204
205+ void U_CALLCONV initIntPropInclusion (UProperty prop, UErrorCode &errorCode) {
206+ // This function is invoked only via umtx_initOnce().
207+ U_ASSERT (UCHAR_INT_START <= prop && prop < UCHAR_INT_LIMIT);
208+ int32_t inclIndex = UPROPS_SRC_COUNT + prop - UCHAR_INT_START;
209+ U_ASSERT (gInclusions [inclIndex].fSet == nullptr );
210+ UPropertySource src = uprops_getSource (prop);
211+ const UnicodeSet *incl = getInclusionsForSource (src, errorCode);
212+ if (U_FAILURE (errorCode)) {
213+ return ;
214+ }
215+
216+ LocalPointer<UnicodeSet> intPropIncl (new UnicodeSet (0 , 0 ));
217+ if (intPropIncl.isNull ()) {
218+ errorCode = U_MEMORY_ALLOCATION_ERROR;
219+ return ;
220+ }
221+ int32_t numRanges = incl->getRangeCount ();
222+ int32_t prevValue = 0 ;
223+ for (int32_t i = 0 ; i < numRanges; ++i) {
224+ UChar32 rangeEnd = incl->getRangeEnd (i);
225+ for (UChar32 c = incl->getRangeStart (i); c <= rangeEnd; ++c) {
226+ // TODO: Get a UCharacterProperty.IntProperty to avoid the property dispatch.
227+ int32_t value = u_getIntPropertyValue (c, prop);
228+ if (value != prevValue) {
229+ intPropIncl->add (c);
230+ prevValue = value;
231+ }
232+ }
233+ }
234+
235+ if (intPropIncl->isBogus ()) {
236+ errorCode = U_MEMORY_ALLOCATION_ERROR;
237+ return ;
238+ }
239+ // Compact for caching.
240+ intPropIncl->compact ();
241+ gInclusions [inclIndex].fSet = intPropIncl.orphan ();
242+ ucln_common_registerCleanup (UCLN_COMMON_CHARACTERPROPERTIES, characterproperties_cleanup);
243+ }
244+
245+ } // namespace
246+
247+ U_NAMESPACE_BEGIN
248+
206249const UnicodeSet *CharacterProperties::getInclusionsForProperty (
207250 UProperty prop, UErrorCode &errorCode) {
208251 if (U_FAILURE (errorCode)) { return nullptr ; }
209- UPropertySource src = uprops_getSource (prop);
210- return getInclusionsForSource (src, errorCode);
252+ if (UCHAR_INT_START <= prop && prop < UCHAR_INT_LIMIT) {
253+ int32_t inclIndex = UPROPS_SRC_COUNT + prop - UCHAR_INT_START;
254+ Inclusion &i = gInclusions [inclIndex];
255+ umtx_initOnce (i.fInitOnce , &initIntPropInclusion, prop, errorCode);
256+ return i.fSet ;
257+ } else {
258+ UPropertySource src = uprops_getSource (prop);
259+ return getInclusionsForSource (src, errorCode);
260+ }
211261}
212262
213263U_NAMESPACE_END
@@ -216,7 +266,7 @@ namespace {
216266
217267UnicodeSet *makeSet (UProperty property, UErrorCode &errorCode) {
218268 if (U_FAILURE (errorCode)) { return nullptr ; }
219- icu:: LocalPointer<UnicodeSet> set (new UnicodeSet ());
269+ LocalPointer<UnicodeSet> set (new UnicodeSet ());
220270 if (set.isNull ()) {
221271 errorCode = U_MEMORY_ALLOCATION_ERROR;
222272 return nullptr ;
@@ -311,7 +361,7 @@ u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode) {
311361 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
312362 return nullptr ;
313363 }
314- Mutex m (& cpMutex);
364+ Mutex m (cpMutex () );
315365 UnicodeSet *set = sets[property];
316366 if (set == nullptr ) {
317367 sets[property] = set = makeSet (property, *pErrorCode);
@@ -327,7 +377,7 @@ u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode) {
327377 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
328378 return nullptr ;
329379 }
330- Mutex m (& cpMutex);
380+ Mutex m (cpMutex () );
331381 UCPMap *map = maps[property - UCHAR_INT_START];
332382 if (map == nullptr ) {
333383 maps[property - UCHAR_INT_START] = map = makeMap (property, *pErrorCode);
0 commit comments