23
23
#include " umutex.h"
24
24
#include " uprops.h"
25
25
26
+ using icu::LocalPointer;
27
+ #if !UCONFIG_NO_NORMALIZATION
28
+ using icu::Normalizer2Factory;
29
+ using icu::Normalizer2Impl;
30
+ #endif
26
31
using icu::UInitOnce;
27
32
using icu::UnicodeSet;
28
33
29
34
namespace {
30
35
31
36
UBool U_CALLCONV characterproperties_cleanup ();
32
37
38
+ constexpr int32_t NUM_INCLUSIONS = UPROPS_SRC_COUNT + UCHAR_INT_LIMIT - UCHAR_INT_START;
39
+
33
40
struct Inclusion {
34
41
UnicodeSet *fSet ;
35
42
UInitOnce fInitOnce ;
36
43
};
37
- Inclusion gInclusions [UPROPS_SRC_COUNT ]; // cached getInclusions()
44
+ Inclusion gInclusions [NUM_INCLUSIONS ]; // cached getInclusions()
38
45
39
46
UnicodeSet *sets[UCHAR_BINARY_LIMIT] = {};
40
47
41
48
UCPMap *maps[UCHAR_INT_LIMIT - UCHAR_INT_START] = {};
42
49
43
- UMutex cpMutex = U_MUTEX_INITIALIZER;
50
+ icu::UMutex *cpMutex () {
51
+ static icu::UMutex m = U_MUTEX_INITIALIZER;
52
+ return &m;
53
+ }
44
54
45
55
// ----------------------------------------------------------------
46
56
// Inclusions list
@@ -80,43 +90,29 @@ UBool U_CALLCONV characterproperties_cleanup() {
80
90
return TRUE ;
81
91
}
82
92
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) {
94
94
// This function is invoked only via umtx_initOnce().
95
- // This function is a friend of class UnicodeSet.
96
-
97
95
U_ASSERT (0 <= src && src < UPROPS_SRC_COUNT);
98
96
if (src == UPROPS_SRC_NONE) {
99
97
errorCode = U_INTERNAL_PROGRAM_ERROR;
100
98
return ;
101
99
}
102
- UnicodeSet * &incl = gInclusions [src].fSet ;
103
- U_ASSERT (incl == nullptr );
100
+ U_ASSERT (gInclusions [src].fSet == nullptr );
104
101
105
- incl = new UnicodeSet ();
106
- if (incl == nullptr ) {
102
+ LocalPointer<UnicodeSet> incl ( new UnicodeSet () );
103
+ if (incl. isNull () ) {
107
104
errorCode = U_MEMORY_ALLOCATION_ERROR;
108
105
return ;
109
106
}
110
107
USetAdder sa = {
111
- (USet *)incl,
108
+ (USet *)incl. getAlias () ,
112
109
_set_add,
113
110
_set_addRange,
114
111
_set_addString,
115
112
nullptr , // don't need remove()
116
113
nullptr // don't need removeRange()
117
114
};
118
115
119
- incl->ensureCapacity (DEFAULT_INCLUSION_CAPACITY, errorCode);
120
116
switch (src) {
121
117
case UPROPS_SRC_CHAR:
122
118
uchar_addPropertyStarts (&sa, &errorCode);
@@ -183,12 +179,15 @@ void U_CALLCONV CharacterProperties::initInclusion(UPropertySource src, UErrorCo
183
179
}
184
180
185
181
if (U_FAILURE (errorCode)) {
186
- delete incl;
187
- incl = nullptr ;
188
182
return ;
189
183
}
190
- // Compact for caching
184
+ if (incl->isBogus ()) {
185
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
186
+ return ;
187
+ }
188
+ // Compact for caching.
191
189
incl->compact ();
190
+ gInclusions [src].fSet = incl.orphan ();
192
191
ucln_common_registerCleanup (UCLN_COMMON_CHARACTERPROPERTIES, characterproperties_cleanup);
193
192
}
194
193
@@ -199,15 +198,66 @@ const UnicodeSet *getInclusionsForSource(UPropertySource src, UErrorCode &errorC
199
198
return nullptr ;
200
199
}
201
200
Inclusion &i = gInclusions [src];
202
- umtx_initOnce (i.fInitOnce , &CharacterProperties:: initInclusion, src, errorCode);
201
+ umtx_initOnce (i.fInitOnce , &initInclusion, src, errorCode);
203
202
return i.fSet ;
204
203
}
205
204
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
+
206
249
const UnicodeSet *CharacterProperties::getInclusionsForProperty (
207
250
UProperty prop, UErrorCode &errorCode) {
208
251
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
+ }
211
261
}
212
262
213
263
U_NAMESPACE_END
@@ -216,7 +266,7 @@ namespace {
216
266
217
267
UnicodeSet *makeSet (UProperty property, UErrorCode &errorCode) {
218
268
if (U_FAILURE (errorCode)) { return nullptr ; }
219
- icu:: LocalPointer<UnicodeSet> set (new UnicodeSet ());
269
+ LocalPointer<UnicodeSet> set (new UnicodeSet ());
220
270
if (set.isNull ()) {
221
271
errorCode = U_MEMORY_ALLOCATION_ERROR;
222
272
return nullptr ;
@@ -311,7 +361,7 @@ u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode) {
311
361
*pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
312
362
return nullptr ;
313
363
}
314
- Mutex m (& cpMutex);
364
+ Mutex m (cpMutex () );
315
365
UnicodeSet *set = sets[property];
316
366
if (set == nullptr ) {
317
367
sets[property] = set = makeSet (property, *pErrorCode);
@@ -327,7 +377,7 @@ u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode) {
327
377
*pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
328
378
return nullptr ;
329
379
}
330
- Mutex m (& cpMutex);
380
+ Mutex m (cpMutex () );
331
381
UCPMap *map = maps[property - UCHAR_INT_START];
332
382
if (map == nullptr ) {
333
383
maps[property - UCHAR_INT_START] = map = makeMap (property, *pErrorCode);
0 commit comments