]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************** | |
46f4442e | 3 | * Copyright (C) 1996-2008, International Business Machines |
b75a7d8f A |
4 | * Corporation and others. All Rights Reserved. |
5 | ******************************************************************************** | |
6 | * | |
7 | * File UCHAR.C | |
8 | * | |
9 | * Modification History: | |
10 | * | |
11 | * Date Name Description | |
12 | * 04/02/97 aliu Creation. | |
13 | * 4/15/99 Madhu Updated all the function definitions for C Implementation | |
14 | * 5/20/99 Madhu Added the function u_getVersion() | |
15 | * 8/19/1999 srl Upgraded scripts to Unicode3.0 | |
16 | * 11/11/1999 weiv added u_isalnum(), cleaned comments | |
17 | * 01/11/2000 helena Renamed u_getVersion to u_getUnicodeVersion. | |
18 | * 06/20/2000 helena OS/400 port changes; mostly typecast. | |
19 | ****************************************************************************** | |
20 | */ | |
21 | ||
22 | #include "unicode/utypes.h" | |
23 | #include "unicode/uchar.h" | |
374ca955 | 24 | #include "unicode/uscript.h" |
b75a7d8f | 25 | #include "unicode/udata.h" |
b75a7d8f A |
26 | #include "umutex.h" |
27 | #include "cmemory.h" | |
28 | #include "ucln_cmn.h" | |
29 | #include "utrie.h" | |
374ca955 A |
30 | #include "udataswp.h" |
31 | #include "unormimp.h" /* JAMO_L_BASE etc. */ | |
b75a7d8f A |
32 | #include "uprops.h" |
33 | ||
34 | #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) | |
35 | ||
36 | /* dynamically loaded Unicode character properties -------------------------- */ | |
37 | ||
73c04bcf A |
38 | #define UCHAR_HARDCODE_DATA 1 |
39 | ||
40 | #if UCHAR_HARDCODE_DATA | |
41 | ||
42 | /* uchar_props_data.c is machine-generated by genprops --csource */ | |
43 | #include "uchar_props_data.c" | |
44 | ||
45 | #else | |
46 | ||
b75a7d8f A |
47 | /* |
48 | * loaded uprops.dat - | |
49 | * for a description of the file format, see icu/source/tools/genprops/store.c | |
50 | */ | |
51 | static const char DATA_NAME[] = "uprops"; | |
52 | static const char DATA_TYPE[] = "icu"; | |
53 | ||
54 | static UDataMemory *propsData=NULL; | |
55 | static UErrorCode dataErrorCode=U_ZERO_ERROR; | |
56 | ||
57 | static uint8_t formatVersion[4]={ 0, 0, 0, 0 }; | |
58 | static UVersionInfo dataVersion={ 0, 0, 0, 0 }; | |
59 | ||
60 | static UTrie propsTrie={ 0 }, propsVectorsTrie={ 0 }; | |
73c04bcf | 61 | static const uint32_t *pData32=NULL, *propsVectors=NULL; |
b75a7d8f A |
62 | static int32_t countPropsVectors=0, propsVectorsColumns=0; |
63 | ||
374ca955 A |
64 | static int8_t havePropsData=0; /* == 0 -> Data has not been loaded. |
65 | * < 0 -> Error occured attempting to load data. | |
66 | * > 0 -> Data has been successfully loaded. | |
67 | */ | |
b75a7d8f A |
68 | |
69 | /* index values loaded from uprops.dat */ | |
70 | static int32_t indexes[UPROPS_INDEX_COUNT]; | |
71 | ||
b75a7d8f A |
72 | static UBool U_CALLCONV |
73 | isAcceptable(void *context, | |
74 | const char *type, const char *name, | |
75 | const UDataInfo *pInfo) { | |
76 | if( | |
77 | pInfo->size>=20 && | |
78 | pInfo->isBigEndian==U_IS_BIG_ENDIAN && | |
79 | pInfo->charsetFamily==U_CHARSET_FAMILY && | |
80 | pInfo->dataFormat[0]==0x55 && /* dataFormat="UPro" */ | |
81 | pInfo->dataFormat[1]==0x50 && | |
82 | pInfo->dataFormat[2]==0x72 && | |
83 | pInfo->dataFormat[3]==0x6f && | |
73c04bcf | 84 | pInfo->formatVersion[0]==4 && |
b75a7d8f A |
85 | pInfo->formatVersion[2]==UTRIE_SHIFT && |
86 | pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT | |
87 | ) { | |
88 | uprv_memcpy(formatVersion, pInfo->formatVersion, 4); | |
89 | uprv_memcpy(dataVersion, pInfo->dataVersion, 4); | |
90 | return TRUE; | |
91 | } else { | |
92 | return FALSE; | |
93 | } | |
94 | } | |
95 | ||
374ca955 | 96 | static UBool U_CALLCONV uchar_cleanup(void) |
b75a7d8f A |
97 | { |
98 | if (propsData) { | |
99 | udata_close(propsData); | |
100 | propsData=NULL; | |
101 | } | |
102 | pData32=NULL; | |
b75a7d8f A |
103 | propsVectors=NULL; |
104 | countPropsVectors=0; | |
73c04bcf | 105 | uprv_memset(dataVersion, 0, U_MAX_VERSION_LENGTH); |
b75a7d8f | 106 | dataErrorCode=U_ZERO_ERROR; |
374ca955 | 107 | havePropsData=0; |
b75a7d8f A |
108 | |
109 | return TRUE; | |
110 | } | |
111 | ||
374ca955 A |
112 | struct UCharProps { |
113 | UDataMemory *propsData; | |
114 | UTrie propsTrie, propsVectorsTrie; | |
115 | const uint32_t *pData32; | |
116 | }; | |
117 | typedef struct UCharProps UCharProps; | |
118 | ||
119 | /* open uprops.icu */ | |
120 | static void | |
121 | _openProps(UCharProps *ucp, UErrorCode *pErrorCode) { | |
122 | const uint32_t *p; | |
123 | int32_t length; | |
124 | ||
125 | ucp->propsData=udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, pErrorCode); | |
126 | if(U_FAILURE(*pErrorCode)) { | |
127 | return; | |
128 | } | |
129 | ||
130 | ucp->pData32=p=(const uint32_t *)udata_getMemory(ucp->propsData); | |
131 | ||
132 | /* unserialize the trie; it is directly after the int32_t indexes[UPROPS_INDEX_COUNT] */ | |
133 | length=(int32_t)p[UPROPS_PROPS32_INDEX]*4; | |
134 | length=utrie_unserialize(&ucp->propsTrie, (const uint8_t *)(p+UPROPS_INDEX_COUNT), length-64, pErrorCode); | |
135 | if(U_FAILURE(*pErrorCode)) { | |
136 | return; | |
137 | } | |
374ca955 | 138 | |
73c04bcf A |
139 | /* unserialize the properties vectors trie */ |
140 | length=(int32_t)(p[UPROPS_ADDITIONAL_VECTORS_INDEX]-p[UPROPS_ADDITIONAL_TRIE_INDEX])*4; | |
141 | if(length>0) { | |
374ca955 | 142 | length=utrie_unserialize(&ucp->propsVectorsTrie, (const uint8_t *)(p+p[UPROPS_ADDITIONAL_TRIE_INDEX]), length, pErrorCode); |
73c04bcf A |
143 | } |
144 | if(length<=0 || U_FAILURE(*pErrorCode)) { | |
145 | /* | |
146 | * length==0: | |
147 | * Allow the properties vectors trie to be missing - | |
148 | * also requires propsVectorsColumns=indexes[UPROPS_ADDITIONAL_VECTORS_COLUMNS_INDEX] | |
149 | * to be zero so that this trie is never accessed. | |
150 | */ | |
151 | uprv_memset(&ucp->propsVectorsTrie, 0, sizeof(ucp->propsVectorsTrie)); | |
374ca955 A |
152 | } |
153 | } | |
154 | ||
73c04bcf A |
155 | #endif |
156 | ||
157 | #if !UCHAR_HARDCODE_DATA | |
158 | static int8_t | |
374ca955 | 159 | uprv_loadPropsData(UErrorCode *pErrorCode) { |
b75a7d8f A |
160 | /* load Unicode character properties data from file if necessary */ |
161 | ||
162 | /* | |
163 | * This lazy intialization with double-checked locking (without mutex protection for | |
164 | * haveNormData==0) is transiently unsafe under certain circumstances. | |
165 | * Check the readme and use u_init() if necessary. | |
166 | */ | |
167 | if(havePropsData==0) { | |
374ca955 | 168 | UCharProps ucp={ NULL }; |
b75a7d8f | 169 | |
374ca955 A |
170 | if(U_FAILURE(*pErrorCode)) { |
171 | return havePropsData; | |
b75a7d8f A |
172 | } |
173 | ||
374ca955 A |
174 | /* open the data outside the mutex block */ |
175 | _openProps(&ucp, pErrorCode); | |
176 | ||
177 | if(U_SUCCESS(*pErrorCode)) { | |
178 | /* in the mutex block, set the data for this process */ | |
179 | umtx_lock(NULL); | |
180 | if(propsData==NULL) { | |
181 | propsData=ucp.propsData; | |
182 | ucp.propsData=NULL; | |
183 | pData32=ucp.pData32; | |
184 | ucp.pData32=NULL; | |
185 | uprv_memcpy(&propsTrie, &ucp.propsTrie, sizeof(propsTrie)); | |
186 | uprv_memcpy(&propsVectorsTrie, &ucp.propsVectorsTrie, sizeof(propsVectorsTrie)); | |
374ca955 | 187 | } |
b75a7d8f | 188 | |
374ca955 A |
189 | /* initialize some variables */ |
190 | uprv_memcpy(indexes, pData32, sizeof(indexes)); | |
374ca955 A |
191 | |
192 | /* additional properties */ | |
193 | if(indexes[UPROPS_ADDITIONAL_VECTORS_INDEX]!=0) { | |
194 | propsVectors=pData32+indexes[UPROPS_ADDITIONAL_VECTORS_INDEX]; | |
195 | countPropsVectors=indexes[UPROPS_RESERVED_INDEX]-indexes[UPROPS_ADDITIONAL_VECTORS_INDEX]; | |
196 | propsVectorsColumns=indexes[UPROPS_ADDITIONAL_VECTORS_COLUMNS_INDEX]; | |
b75a7d8f | 197 | } |
b75a7d8f | 198 | |
374ca955 A |
199 | havePropsData=1; |
200 | umtx_unlock(NULL); | |
201 | } else { | |
202 | dataErrorCode=*pErrorCode; | |
203 | havePropsData=-1; | |
b75a7d8f | 204 | } |
374ca955 A |
205 | ucln_common_registerCleanup(UCLN_COMMON_UCHAR, uchar_cleanup); |
206 | ||
207 | /* if a different thread set it first, then close the extra data */ | |
208 | udata_close(ucp.propsData); /* NULL if it was set correctly */ | |
209 | } | |
210 | ||
211 | return havePropsData; | |
212 | } | |
213 | ||
374ca955 A |
214 | static int8_t |
215 | loadPropsData(void) { | |
216 | UErrorCode errorCode = U_ZERO_ERROR; | |
217 | int8_t retVal = uprv_loadPropsData(&errorCode); | |
218 | return retVal; | |
219 | } | |
220 | ||
73c04bcf | 221 | #endif |
374ca955 | 222 | |
73c04bcf | 223 | /* constants and macros for access to the data ------------------------------ */ |
374ca955 | 224 | |
73c04bcf A |
225 | /* getting a uint32_t properties word from the data */ |
226 | #if UCHAR_HARDCODE_DATA | |
b75a7d8f | 227 | |
73c04bcf | 228 | #define GET_PROPS(c, result) UTRIE_GET16(&propsTrie, c, result); |
b75a7d8f | 229 | |
73c04bcf | 230 | #else |
b75a7d8f | 231 | |
374ca955 | 232 | #define HAVE_DATA (havePropsData>0 || loadPropsData()>0) |
b75a7d8f | 233 | #define GET_PROPS_UNSAFE(c, result) \ |
73c04bcf | 234 | UTRIE_GET16(&propsTrie, c, result); |
b75a7d8f A |
235 | #define GET_PROPS(c, result) \ |
236 | if(HAVE_DATA) { \ | |
237 | GET_PROPS_UNSAFE(c, result); \ | |
238 | } else { \ | |
239 | (result)=0; \ | |
240 | } | |
241 | ||
73c04bcf | 242 | #endif |
b75a7d8f A |
243 | |
244 | U_CFUNC UBool | |
245 | uprv_haveProperties(UErrorCode *pErrorCode) { | |
374ca955 A |
246 | if(U_FAILURE(*pErrorCode)) { |
247 | return FALSE; | |
248 | } | |
73c04bcf | 249 | #if !UCHAR_HARDCODE_DATA |
374ca955 A |
250 | if(havePropsData==0) { |
251 | uprv_loadPropsData(pErrorCode); | |
252 | } | |
253 | if(havePropsData<0) { | |
b75a7d8f A |
254 | *pErrorCode=dataErrorCode; |
255 | return FALSE; | |
256 | } | |
73c04bcf | 257 | #endif |
374ca955 | 258 | return TRUE; |
b75a7d8f A |
259 | } |
260 | ||
261 | /* API functions ------------------------------------------------------------ */ | |
262 | ||
263 | /* Gets the Unicode character's general category.*/ | |
264 | U_CAPI int8_t U_EXPORT2 | |
265 | u_charType(UChar32 c) { | |
266 | uint32_t props; | |
267 | GET_PROPS(c, props); | |
268 | return (int8_t)GET_CATEGORY(props); | |
269 | } | |
270 | ||
271 | /* Enumerate all code points with their general categories. */ | |
272 | struct _EnumTypeCallback { | |
273 | UCharEnumTypeRange *enumRange; | |
274 | const void *context; | |
275 | }; | |
276 | ||
277 | static uint32_t U_CALLCONV | |
278 | _enumTypeValue(const void *context, uint32_t value) { | |
73c04bcf | 279 | return GET_CATEGORY(value); |
b75a7d8f A |
280 | } |
281 | ||
282 | static UBool U_CALLCONV | |
283 | _enumTypeRange(const void *context, UChar32 start, UChar32 limit, uint32_t value) { | |
284 | /* just cast the value to UCharCategory */ | |
285 | return ((struct _EnumTypeCallback *)context)-> | |
286 | enumRange(((struct _EnumTypeCallback *)context)->context, | |
287 | start, limit, (UCharCategory)value); | |
288 | } | |
289 | ||
290 | U_CAPI void U_EXPORT2 | |
291 | u_enumCharTypes(UCharEnumTypeRange *enumRange, const void *context) { | |
292 | struct _EnumTypeCallback callback; | |
293 | ||
73c04bcf A |
294 | if(enumRange==NULL |
295 | #if !UCHAR_HARDCODE_DATA | |
296 | || !HAVE_DATA | |
297 | #endif | |
298 | ) { | |
b75a7d8f A |
299 | return; |
300 | } | |
301 | ||
302 | callback.enumRange=enumRange; | |
303 | callback.context=context; | |
304 | utrie_enum(&propsTrie, _enumTypeValue, _enumTypeRange, &callback); | |
305 | } | |
306 | ||
307 | /* Checks if ch is a lower case letter.*/ | |
308 | U_CAPI UBool U_EXPORT2 | |
309 | u_islower(UChar32 c) { | |
310 | uint32_t props; | |
311 | GET_PROPS(c, props); | |
312 | return (UBool)(GET_CATEGORY(props)==U_LOWERCASE_LETTER); | |
313 | } | |
314 | ||
315 | /* Checks if ch is an upper case letter.*/ | |
316 | U_CAPI UBool U_EXPORT2 | |
317 | u_isupper(UChar32 c) { | |
318 | uint32_t props; | |
319 | GET_PROPS(c, props); | |
320 | return (UBool)(GET_CATEGORY(props)==U_UPPERCASE_LETTER); | |
321 | } | |
322 | ||
323 | /* Checks if ch is a title case letter; usually upper case letters.*/ | |
324 | U_CAPI UBool U_EXPORT2 | |
325 | u_istitle(UChar32 c) { | |
326 | uint32_t props; | |
327 | GET_PROPS(c, props); | |
328 | return (UBool)(GET_CATEGORY(props)==U_TITLECASE_LETTER); | |
329 | } | |
330 | ||
331 | /* Checks if ch is a decimal digit. */ | |
332 | U_CAPI UBool U_EXPORT2 | |
333 | u_isdigit(UChar32 c) { | |
334 | uint32_t props; | |
335 | GET_PROPS(c, props); | |
336 | return (UBool)(GET_CATEGORY(props)==U_DECIMAL_DIGIT_NUMBER); | |
337 | } | |
338 | ||
339 | U_CAPI UBool U_EXPORT2 | |
340 | u_isxdigit(UChar32 c) { | |
341 | uint32_t props; | |
342 | ||
343 | /* check ASCII and Fullwidth ASCII a-fA-F */ | |
344 | if( | |
345 | (c<=0x66 && c>=0x41 && (c<=0x46 || c>=0x61)) || | |
346 | (c>=0xff21 && c<=0xff46 && (c<=0xff26 || c>=0xff41)) | |
347 | ) { | |
348 | return TRUE; | |
349 | } | |
350 | ||
351 | GET_PROPS(c, props); | |
352 | return (UBool)(GET_CATEGORY(props)==U_DECIMAL_DIGIT_NUMBER); | |
353 | } | |
354 | ||
355 | /* Checks if the Unicode character is a letter.*/ | |
356 | U_CAPI UBool U_EXPORT2 | |
357 | u_isalpha(UChar32 c) { | |
358 | uint32_t props; | |
359 | GET_PROPS(c, props); | |
360 | return (UBool)((CAT_MASK(props)&U_GC_L_MASK)!=0); | |
361 | } | |
362 | ||
374ca955 A |
363 | U_CAPI UBool U_EXPORT2 |
364 | u_isUAlphabetic(UChar32 c) { | |
365 | return (u_getUnicodeProperties(c, 1)&U_MASK(UPROPS_ALPHABETIC))!=0; | |
366 | } | |
367 | ||
73c04bcf | 368 | /* Checks if c is a letter or a decimal digit */ |
b75a7d8f A |
369 | U_CAPI UBool U_EXPORT2 |
370 | u_isalnum(UChar32 c) { | |
371 | uint32_t props; | |
372 | GET_PROPS(c, props); | |
373 | return (UBool)((CAT_MASK(props)&(U_GC_L_MASK|U_GC_ND_MASK))!=0); | |
374 | } | |
375 | ||
73c04bcf A |
376 | /** |
377 | * Checks if c is alphabetic, or a decimal digit; implements UCHAR_POSIX_ALNUM. | |
378 | * @internal | |
379 | */ | |
380 | U_CFUNC UBool | |
381 | u_isalnumPOSIX(UChar32 c) { | |
382 | return (UBool)(u_isUAlphabetic(c) || u_isdigit(c)); | |
383 | } | |
384 | ||
b75a7d8f A |
385 | /* Checks if ch is a unicode character with assigned character type.*/ |
386 | U_CAPI UBool U_EXPORT2 | |
387 | u_isdefined(UChar32 c) { | |
388 | uint32_t props; | |
389 | GET_PROPS(c, props); | |
390 | return (UBool)(GET_CATEGORY(props)!=0); | |
391 | } | |
392 | ||
393 | /* Checks if the Unicode character is a base form character that can take a diacritic.*/ | |
394 | U_CAPI UBool U_EXPORT2 | |
395 | u_isbase(UChar32 c) { | |
396 | uint32_t props; | |
397 | GET_PROPS(c, props); | |
398 | return (UBool)((CAT_MASK(props)&(U_GC_L_MASK|U_GC_N_MASK|U_GC_MC_MASK|U_GC_ME_MASK))!=0); | |
399 | } | |
400 | ||
401 | /* Checks if the Unicode character is a control character.*/ | |
402 | U_CAPI UBool U_EXPORT2 | |
403 | u_iscntrl(UChar32 c) { | |
404 | uint32_t props; | |
405 | GET_PROPS(c, props); | |
406 | return (UBool)((CAT_MASK(props)&(U_GC_CC_MASK|U_GC_CF_MASK|U_GC_ZL_MASK|U_GC_ZP_MASK))!=0); | |
407 | } | |
408 | ||
409 | U_CAPI UBool U_EXPORT2 | |
410 | u_isISOControl(UChar32 c) { | |
411 | return (uint32_t)c<=0x9f && (c<=0x1f || c>=0x7f); | |
412 | } | |
413 | ||
414 | /* Some control characters that are used as space. */ | |
415 | #define IS_THAT_CONTROL_SPACE(c) \ | |
416 | (c<=0x9f && ((c>=TAB && c<=CR) || (c>=0x1c && c <=0x1f) || c==NL)) | |
417 | ||
418 | /* Checks if the Unicode character is a space character.*/ | |
419 | U_CAPI UBool U_EXPORT2 | |
420 | u_isspace(UChar32 c) { | |
421 | uint32_t props; | |
422 | GET_PROPS(c, props); | |
423 | return (UBool)((CAT_MASK(props)&U_GC_Z_MASK)!=0 || IS_THAT_CONTROL_SPACE(c)); | |
424 | } | |
425 | ||
426 | U_CAPI UBool U_EXPORT2 | |
427 | u_isJavaSpaceChar(UChar32 c) { | |
428 | uint32_t props; | |
429 | GET_PROPS(c, props); | |
430 | return (UBool)((CAT_MASK(props)&U_GC_Z_MASK)!=0); | |
431 | } | |
432 | ||
433 | /* Checks if the Unicode character is a whitespace character.*/ | |
434 | U_CAPI UBool U_EXPORT2 | |
435 | u_isWhitespace(UChar32 c) { | |
436 | uint32_t props; | |
437 | GET_PROPS(c, props); | |
438 | return (UBool)( | |
439 | ((CAT_MASK(props)&U_GC_Z_MASK)!=0 && | |
440 | c!=NBSP && c!=FIGURESP && c!=NNBSP) || /* exclude no-break spaces */ | |
441 | IS_THAT_CONTROL_SPACE(c) | |
442 | ); | |
443 | } | |
444 | ||
445 | U_CAPI UBool U_EXPORT2 | |
446 | u_isblank(UChar32 c) { | |
447 | if((uint32_t)c<=0x9f) { | |
448 | return c==9 || c==0x20; /* TAB or SPACE */ | |
449 | } else { | |
73c04bcf A |
450 | /* Zs */ |
451 | uint32_t props; | |
452 | GET_PROPS(c, props); | |
453 | return (UBool)(GET_CATEGORY(props)==U_SPACE_SEPARATOR); | |
b75a7d8f A |
454 | } |
455 | } | |
456 | ||
374ca955 A |
457 | U_CAPI UBool U_EXPORT2 |
458 | u_isUWhiteSpace(UChar32 c) { | |
459 | return (u_getUnicodeProperties(c, 1)&U_MASK(UPROPS_WHITE_SPACE))!=0; | |
460 | } | |
461 | ||
b75a7d8f A |
462 | /* Checks if the Unicode character is printable.*/ |
463 | U_CAPI UBool U_EXPORT2 | |
464 | u_isprint(UChar32 c) { | |
465 | uint32_t props; | |
466 | GET_PROPS(c, props); | |
467 | /* comparing ==0 returns FALSE for the categories mentioned */ | |
468 | return (UBool)((CAT_MASK(props)&U_GC_C_MASK)==0); | |
469 | } | |
470 | ||
73c04bcf A |
471 | /** |
472 | * Checks if c is in \p{graph}\p{blank} - \p{cntrl}. | |
473 | * Implements UCHAR_POSIX_PRINT. | |
474 | * @internal | |
475 | */ | |
476 | U_CFUNC UBool | |
477 | u_isprintPOSIX(UChar32 c) { | |
478 | uint32_t props; | |
479 | GET_PROPS(c, props); | |
480 | /* | |
481 | * The only cntrl character in graph+blank is TAB (in blank). | |
482 | * Here we implement (blank-TAB)=Zs instead of calling u_isblank(). | |
483 | */ | |
484 | return (UBool)((GET_CATEGORY(props)==U_SPACE_SEPARATOR) || u_isgraphPOSIX(c)); | |
485 | } | |
486 | ||
b75a7d8f A |
487 | U_CAPI UBool U_EXPORT2 |
488 | u_isgraph(UChar32 c) { | |
489 | uint32_t props; | |
490 | GET_PROPS(c, props); | |
491 | /* comparing ==0 returns FALSE for the categories mentioned */ | |
492 | return (UBool)((CAT_MASK(props)& | |
493 | (U_GC_CC_MASK|U_GC_CF_MASK|U_GC_CS_MASK|U_GC_CN_MASK|U_GC_Z_MASK)) | |
494 | ==0); | |
495 | } | |
496 | ||
73c04bcf A |
497 | /** |
498 | * Checks if c is in | |
499 | * [^\p{space}\p{gc=Control}\p{gc=Surrogate}\p{gc=Unassigned}] | |
500 | * with space=\p{Whitespace} and Control=Cc. | |
501 | * Implements UCHAR_POSIX_GRAPH. | |
502 | * @internal | |
503 | */ | |
504 | U_CFUNC UBool | |
505 | u_isgraphPOSIX(UChar32 c) { | |
506 | uint32_t props; | |
507 | GET_PROPS(c, props); | |
508 | /* \p{space}\p{gc=Control} == \p{gc=Z}\p{Control} */ | |
509 | /* comparing ==0 returns FALSE for the categories mentioned */ | |
510 | return (UBool)((CAT_MASK(props)& | |
511 | (U_GC_CC_MASK|U_GC_CS_MASK|U_GC_CN_MASK|U_GC_Z_MASK)) | |
512 | ==0); | |
513 | } | |
514 | ||
b75a7d8f A |
515 | U_CAPI UBool U_EXPORT2 |
516 | u_ispunct(UChar32 c) { | |
517 | uint32_t props; | |
518 | GET_PROPS(c, props); | |
519 | return (UBool)((CAT_MASK(props)&U_GC_P_MASK)!=0); | |
520 | } | |
521 | ||
522 | /* Checks if the Unicode character can start a Unicode identifier.*/ | |
523 | U_CAPI UBool U_EXPORT2 | |
524 | u_isIDStart(UChar32 c) { | |
525 | /* same as u_isalpha() */ | |
526 | uint32_t props; | |
527 | GET_PROPS(c, props); | |
528 | return (UBool)((CAT_MASK(props)&(U_GC_L_MASK|U_GC_NL_MASK))!=0); | |
529 | } | |
530 | ||
531 | /* Checks if the Unicode character can be a Unicode identifier part other than starting the | |
532 | identifier.*/ | |
533 | U_CAPI UBool U_EXPORT2 | |
534 | u_isIDPart(UChar32 c) { | |
535 | uint32_t props; | |
536 | GET_PROPS(c, props); | |
537 | return (UBool)( | |
538 | (CAT_MASK(props)& | |
539 | (U_GC_ND_MASK|U_GC_NL_MASK| | |
540 | U_GC_L_MASK| | |
541 | U_GC_PC_MASK|U_GC_MC_MASK|U_GC_MN_MASK) | |
542 | )!=0 || | |
543 | u_isIDIgnorable(c)); | |
544 | } | |
545 | ||
546 | /*Checks if the Unicode character can be ignorable in a Java or Unicode identifier.*/ | |
547 | U_CAPI UBool U_EXPORT2 | |
548 | u_isIDIgnorable(UChar32 c) { | |
549 | if(c<=0x9f) { | |
550 | return u_isISOControl(c) && !IS_THAT_CONTROL_SPACE(c); | |
551 | } else { | |
552 | uint32_t props; | |
553 | GET_PROPS(c, props); | |
554 | return (UBool)(GET_CATEGORY(props)==U_FORMAT_CHAR); | |
555 | } | |
556 | } | |
557 | ||
558 | /*Checks if the Unicode character can start a Java identifier.*/ | |
559 | U_CAPI UBool U_EXPORT2 | |
560 | u_isJavaIDStart(UChar32 c) { | |
561 | uint32_t props; | |
562 | GET_PROPS(c, props); | |
563 | return (UBool)((CAT_MASK(props)&(U_GC_L_MASK|U_GC_SC_MASK|U_GC_PC_MASK))!=0); | |
564 | } | |
565 | ||
566 | /*Checks if the Unicode character can be a Java identifier part other than starting the | |
567 | * identifier. | |
568 | */ | |
569 | U_CAPI UBool U_EXPORT2 | |
570 | u_isJavaIDPart(UChar32 c) { | |
571 | uint32_t props; | |
572 | GET_PROPS(c, props); | |
573 | return (UBool)( | |
574 | (CAT_MASK(props)& | |
575 | (U_GC_ND_MASK|U_GC_NL_MASK| | |
576 | U_GC_L_MASK| | |
577 | U_GC_SC_MASK|U_GC_PC_MASK| | |
578 | U_GC_MC_MASK|U_GC_MN_MASK) | |
579 | )!=0 || | |
580 | u_isIDIgnorable(c)); | |
581 | } | |
582 | ||
b75a7d8f A |
583 | U_CAPI int32_t U_EXPORT2 |
584 | u_charDigitValue(UChar32 c) { | |
73c04bcf | 585 | uint32_t props; |
b75a7d8f | 586 | GET_PROPS(c, props); |
b75a7d8f | 587 | |
73c04bcf A |
588 | if(GET_NUMERIC_TYPE(props)==1) { |
589 | return GET_NUMERIC_VALUE(props); | |
590 | } else { | |
591 | return -1; | |
b75a7d8f | 592 | } |
b75a7d8f A |
593 | } |
594 | ||
595 | U_CAPI double U_EXPORT2 | |
596 | u_getNumericValue(UChar32 c) { | |
73c04bcf | 597 | uint32_t props, numericType, numericValue; |
b75a7d8f A |
598 | GET_PROPS(c, props); |
599 | numericType=GET_NUMERIC_TYPE(props); | |
600 | ||
73c04bcf | 601 | if(numericType==0 || numericType>=UPROPS_NT_COUNT) { |
b75a7d8f | 602 | return U_NO_NUMERIC_VALUE; |
b75a7d8f | 603 | } |
b75a7d8f | 604 | |
73c04bcf | 605 | numericValue=GET_NUMERIC_VALUE(props); |
b75a7d8f | 606 | |
73c04bcf A |
607 | if(numericType<U_NT_COUNT) { |
608 | /* normal type, the value is stored directly */ | |
609 | return numericValue; | |
610 | } else if(numericType==UPROPS_NT_FRACTION) { | |
611 | /* fraction value */ | |
612 | int32_t numerator; | |
613 | uint32_t denominator; | |
b75a7d8f | 614 | |
73c04bcf A |
615 | numerator=(int32_t)numericValue>>UPROPS_FRACTION_NUM_SHIFT; |
616 | denominator=(numericValue&UPROPS_FRACTION_DEN_MASK)+UPROPS_FRACTION_DEN_OFFSET; | |
617 | ||
618 | if(numerator==0) { | |
619 | numerator=-1; | |
620 | } | |
621 | return (double)numerator/(double)denominator; | |
622 | } else /* numericType==UPROPS_NT_LARGE */ { | |
623 | /* large value with exponent */ | |
624 | double numValue; | |
625 | int32_t mant, exp; | |
626 | ||
627 | mant=(int32_t)numericValue>>UPROPS_LARGE_MANT_SHIFT; | |
628 | exp=(int32_t)numericValue&UPROPS_LARGE_EXP_MASK; | |
629 | if(mant==0) { | |
630 | mant=1; | |
631 | exp+=UPROPS_LARGE_EXP_OFFSET_EXTRA; | |
632 | } else if(mant>9) { | |
633 | return U_NO_NUMERIC_VALUE; /* reserved mantissa value */ | |
b75a7d8f | 634 | } else { |
73c04bcf | 635 | exp+=UPROPS_LARGE_EXP_OFFSET; |
b75a7d8f | 636 | } |
73c04bcf A |
637 | |
638 | numValue=mant; | |
639 | ||
640 | /* multiply by 10^exp without math.h */ | |
641 | while(exp>=4) { | |
642 | numValue*=10000.; | |
643 | exp-=4; | |
644 | } | |
645 | switch(exp) { | |
646 | case 3: | |
647 | numValue*=1000.; | |
648 | break; | |
649 | case 2: | |
650 | numValue*=100.; | |
651 | break; | |
652 | case 1: | |
653 | numValue*=10.; | |
654 | break; | |
655 | case 0: | |
656 | default: | |
657 | break; | |
658 | } | |
659 | ||
660 | return numValue; | |
b75a7d8f A |
661 | } |
662 | } | |
663 | ||
73c04bcf A |
664 | /* ICU 3.4: bidi/shaping properties moved to ubidi_props.c */ |
665 | ||
b75a7d8f A |
666 | /* ICU 2.1: u_getCombiningClass() moved to unorm.cpp */ |
667 | ||
668 | U_CAPI int32_t U_EXPORT2 | |
669 | u_digit(UChar32 ch, int8_t radix) { | |
670 | int8_t value; | |
671 | if((uint8_t)(radix-2)<=(36-2)) { | |
672 | value=(int8_t)u_charDigitValue(ch); | |
673 | if(value<0) { | |
674 | /* ch is not a decimal digit, try latin letters */ | |
675 | if(ch>=0x61 && ch<=0x7A) { | |
676 | value=(int8_t)(ch-0x57); /* ch - 'a' + 10 */ | |
677 | } else if(ch>=0x41 && ch<=0x5A) { | |
678 | value=(int8_t)(ch-0x37); /* ch - 'A' + 10 */ | |
679 | } else if(ch>=0xFF41 && ch<=0xFF5A) { | |
680 | value=(int8_t)(ch-0xFF37); /* fullwidth ASCII a-z */ | |
681 | } else if(ch>=0xFF21 && ch<=0xFF3A) { | |
682 | value=(int8_t)(ch-0xFF17); /* fullwidth ASCII A-Z */ | |
683 | } | |
684 | } | |
685 | } else { | |
686 | value=-1; /* invalid radix */ | |
687 | } | |
688 | return (int8_t)((value<radix) ? value : -1); | |
689 | } | |
690 | ||
691 | U_CAPI UChar32 U_EXPORT2 | |
692 | u_forDigit(int32_t digit, int8_t radix) { | |
693 | if((uint8_t)(radix-2)>(36-2) || (uint32_t)digit>=(uint32_t)radix) { | |
694 | return 0; | |
695 | } else if(digit<10) { | |
696 | return (UChar32)(0x30+digit); | |
697 | } else { | |
698 | return (UChar32)((0x61-10)+digit); | |
699 | } | |
700 | } | |
701 | ||
702 | /* miscellaneous, and support for uprops.c ---------------------------------- */ | |
703 | ||
704 | U_CAPI void U_EXPORT2 | |
705 | u_getUnicodeVersion(UVersionInfo versionArray) { | |
706 | if(versionArray!=NULL) { | |
73c04bcf | 707 | uprv_memcpy(versionArray, dataVersion, U_MAX_VERSION_LENGTH); |
b75a7d8f A |
708 | } |
709 | } | |
710 | ||
711 | U_CFUNC uint32_t | |
712 | u_getUnicodeProperties(UChar32 c, int32_t column) { | |
713 | uint16_t vecIndex; | |
714 | ||
715 | if(column==-1) { | |
716 | uint32_t props; | |
717 | GET_PROPS(c, props); | |
718 | return props; | |
73c04bcf A |
719 | } else if( |
720 | #if !UCHAR_HARDCODE_DATA | |
721 | !HAVE_DATA || countPropsVectors==0 || | |
722 | #endif | |
b75a7d8f A |
723 | column<0 || column>=propsVectorsColumns |
724 | ) { | |
725 | return 0; | |
726 | } else { | |
727 | UTRIE_GET16(&propsVectorsTrie, c, vecIndex); | |
728 | return propsVectors[vecIndex+column]; | |
729 | } | |
730 | } | |
731 | ||
732 | U_CFUNC int32_t | |
733 | uprv_getMaxValues(int32_t column) { | |
73c04bcf | 734 | #if !UCHAR_HARDCODE_DATA |
b75a7d8f | 735 | if(HAVE_DATA) { |
73c04bcf | 736 | #endif |
b75a7d8f A |
737 | switch(column) { |
738 | case 0: | |
739 | return indexes[UPROPS_MAX_VALUES_INDEX]; | |
740 | case 2: | |
741 | return indexes[UPROPS_MAX_VALUES_2_INDEX]; | |
742 | default: | |
743 | return 0; | |
744 | } | |
73c04bcf | 745 | #if !UCHAR_HARDCODE_DATA |
b75a7d8f A |
746 | } else { |
747 | return 0; | |
748 | } | |
73c04bcf | 749 | #endif |
b75a7d8f A |
750 | } |
751 | ||
374ca955 A |
752 | /* |
753 | * get Hangul Syllable Type | |
754 | * implemented here so that uchar.c (uhst_addPropertyStarts()) | |
755 | * does not depend on uprops.c (u_getIntPropertyValue(c, UCHAR_HANGUL_SYLLABLE_TYPE)) | |
756 | */ | |
757 | U_CFUNC UHangulSyllableType | |
758 | uchar_getHST(UChar32 c) { | |
759 | /* purely algorithmic; hardcode known characters, check for assigned new ones */ | |
760 | if(c<JAMO_L_BASE) { | |
761 | /* U_HST_NOT_APPLICABLE */ | |
762 | } else if(c<=0x11ff) { | |
763 | /* Jamo range */ | |
764 | if(c<=0x115f) { | |
765 | /* Jamo L range, HANGUL CHOSEONG ... */ | |
766 | if(c==0x115f || c<=0x1159 || u_charType(c)==U_OTHER_LETTER) { | |
767 | return U_HST_LEADING_JAMO; | |
768 | } | |
769 | } else if(c<=0x11a7) { | |
770 | /* Jamo V range, HANGUL JUNGSEONG ... */ | |
771 | if(c<=0x11a2 || u_charType(c)==U_OTHER_LETTER) { | |
772 | return U_HST_VOWEL_JAMO; | |
773 | } | |
774 | } else { | |
775 | /* Jamo T range */ | |
776 | if(c<=0x11f9 || u_charType(c)==U_OTHER_LETTER) { | |
777 | return U_HST_TRAILING_JAMO; | |
778 | } | |
779 | } | |
780 | } else if((c-=HANGUL_BASE)<0) { | |
781 | /* U_HST_NOT_APPLICABLE */ | |
782 | } else if(c<HANGUL_COUNT) { | |
783 | /* Hangul syllable */ | |
784 | return c%JAMO_T_COUNT==0 ? U_HST_LV_SYLLABLE : U_HST_LVT_SYLLABLE; | |
785 | } | |
786 | return U_HST_NOT_APPLICABLE; | |
b75a7d8f A |
787 | } |
788 | ||
374ca955 A |
789 | U_CAPI void U_EXPORT2 |
790 | u_charAge(UChar32 c, UVersionInfo versionArray) { | |
791 | if(versionArray!=NULL) { | |
792 | uint32_t version=u_getUnicodeProperties(c, 0)>>UPROPS_AGE_SHIFT; | |
793 | versionArray[0]=(uint8_t)(version>>4); | |
794 | versionArray[1]=(uint8_t)(version&0xf); | |
795 | versionArray[2]=versionArray[3]=0; | |
796 | } | |
797 | } | |
b75a7d8f | 798 | |
374ca955 A |
799 | U_CAPI UScriptCode U_EXPORT2 |
800 | uscript_getScript(UChar32 c, UErrorCode *pErrorCode) { | |
801 | if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { | |
73c04bcf | 802 | return USCRIPT_INVALID_CODE; |
374ca955 A |
803 | } |
804 | if((uint32_t)c>0x10ffff) { | |
805 | *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; | |
73c04bcf | 806 | return USCRIPT_INVALID_CODE; |
374ca955 A |
807 | } |
808 | ||
809 | return (UScriptCode)(u_getUnicodeProperties(c, 0)&UPROPS_SCRIPT_MASK); | |
810 | } | |
811 | ||
812 | U_CAPI UBlockCode U_EXPORT2 | |
813 | ublock_getCode(UChar32 c) { | |
814 | return (UBlockCode)((u_getUnicodeProperties(c, 0)&UPROPS_BLOCK_MASK)>>UPROPS_BLOCK_SHIFT); | |
815 | } | |
816 | ||
817 | /* property starts for UnicodeSet ------------------------------------------- */ | |
818 | ||
819 | /* for Hangul_Syllable_Type */ | |
46f4442e | 820 | U_CFUNC void U_EXPORT2 |
73c04bcf | 821 | uhst_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) { |
b75a7d8f A |
822 | UChar32 c; |
823 | int32_t value, value2; | |
824 | ||
374ca955 A |
825 | if(U_FAILURE(*pErrorCode)) { |
826 | return; | |
827 | } | |
828 | ||
73c04bcf | 829 | #if !UCHAR_HARDCODE_DATA |
b75a7d8f A |
830 | if(!HAVE_DATA) { |
831 | *pErrorCode=dataErrorCode; | |
832 | return; | |
833 | } | |
73c04bcf | 834 | #endif |
b75a7d8f | 835 | |
b75a7d8f A |
836 | /* add code points with hardcoded properties, plus the ones following them */ |
837 | ||
b75a7d8f A |
838 | /* |
839 | * Add Jamo type boundaries for UCHAR_HANGUL_SYLLABLE_TYPE. | |
840 | * First, we add fixed boundaries for the blocks of Jamos. | |
841 | * Then we check in loops to see where the current Unicode version | |
842 | * actually stops assigning such Jamos. We start each loop | |
843 | * at the end of the per-Jamo-block assignments in Unicode 4 or earlier. | |
844 | * (These have not changed since Unicode 2.) | |
845 | */ | |
374ca955 | 846 | sa->add(sa->set, 0x1100); |
b75a7d8f A |
847 | value=U_HST_LEADING_JAMO; |
848 | for(c=0x115a; c<=0x115f; ++c) { | |
374ca955 | 849 | value2=uchar_getHST(c); |
b75a7d8f A |
850 | if(value!=value2) { |
851 | value=value2; | |
374ca955 | 852 | sa->add(sa->set, c); |
b75a7d8f A |
853 | } |
854 | } | |
855 | ||
374ca955 | 856 | sa->add(sa->set, 0x1160); |
b75a7d8f A |
857 | value=U_HST_VOWEL_JAMO; |
858 | for(c=0x11a3; c<=0x11a7; ++c) { | |
374ca955 | 859 | value2=uchar_getHST(c); |
b75a7d8f A |
860 | if(value!=value2) { |
861 | value=value2; | |
374ca955 | 862 | sa->add(sa->set, c); |
b75a7d8f A |
863 | } |
864 | } | |
865 | ||
374ca955 | 866 | sa->add(sa->set, 0x11a8); |
b75a7d8f A |
867 | value=U_HST_TRAILING_JAMO; |
868 | for(c=0x11fa; c<=0x11ff; ++c) { | |
374ca955 | 869 | value2=uchar_getHST(c); |
b75a7d8f A |
870 | if(value!=value2) { |
871 | value=value2; | |
374ca955 | 872 | sa->add(sa->set, c); |
b75a7d8f A |
873 | } |
874 | } | |
875 | ||
374ca955 A |
876 | /* Add Hangul type boundaries for UCHAR_HANGUL_SYLLABLE_TYPE. */ |
877 | for(c=HANGUL_BASE; c<(HANGUL_BASE+HANGUL_COUNT); c+=JAMO_T_COUNT) { | |
878 | sa->add(sa->set, c); | |
879 | sa->add(sa->set, c+1); | |
b75a7d8f | 880 | } |
374ca955 | 881 | sa->add(sa->set, c); |
b75a7d8f A |
882 | } |
883 | ||
374ca955 A |
884 | static UBool U_CALLCONV |
885 | _enumPropertyStartsRange(const void *context, UChar32 start, UChar32 limit, uint32_t value) { | |
886 | /* add the start code point to the USet */ | |
73c04bcf | 887 | const USetAdder *sa=(const USetAdder *)context; |
374ca955 A |
888 | sa->add(sa->set, start); |
889 | return TRUE; | |
b75a7d8f A |
890 | } |
891 | ||
374ca955 | 892 | #define USET_ADD_CP_AND_NEXT(sa, cp) sa->add(sa->set, cp); sa->add(sa->set, cp+1) |
b75a7d8f | 893 | |
46f4442e | 894 | U_CFUNC void U_EXPORT2 |
73c04bcf | 895 | uchar_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) { |
374ca955 A |
896 | if(U_FAILURE(*pErrorCode)) { |
897 | return; | |
b75a7d8f | 898 | } |
b75a7d8f | 899 | |
73c04bcf | 900 | #if !UCHAR_HARDCODE_DATA |
b75a7d8f | 901 | if(!HAVE_DATA) { |
374ca955 A |
902 | *pErrorCode=dataErrorCode; |
903 | return; | |
b75a7d8f | 904 | } |
73c04bcf | 905 | #endif |
b75a7d8f | 906 | |
73c04bcf | 907 | /* add the start code point of each same-value range of the main trie */ |
374ca955 | 908 | utrie_enum(&propsTrie, NULL, _enumPropertyStartsRange, sa); |
b75a7d8f | 909 | |
374ca955 | 910 | /* add code points with hardcoded properties, plus the ones following them */ |
b75a7d8f | 911 | |
73c04bcf A |
912 | /* add for u_isblank() */ |
913 | USET_ADD_CP_AND_NEXT(sa, TAB); | |
914 | ||
374ca955 | 915 | /* add for IS_THAT_CONTROL_SPACE() */ |
73c04bcf | 916 | sa->add(sa->set, CR+1); /* range TAB..CR */ |
374ca955 A |
917 | sa->add(sa->set, 0x1c); |
918 | sa->add(sa->set, 0x1f+1); | |
919 | USET_ADD_CP_AND_NEXT(sa, NL); | |
b75a7d8f | 920 | |
374ca955 A |
921 | /* add for u_isIDIgnorable() what was not added above */ |
922 | sa->add(sa->set, DEL); /* range DEL..NBSP-1, NBSP added below */ | |
923 | sa->add(sa->set, HAIRSP); | |
924 | sa->add(sa->set, RLM+1); | |
925 | sa->add(sa->set, INHSWAP); | |
926 | sa->add(sa->set, NOMDIG+1); | |
927 | USET_ADD_CP_AND_NEXT(sa, ZWNBSP); | |
b75a7d8f | 928 | |
374ca955 A |
929 | /* add no-break spaces for u_isWhitespace() what was not added above */ |
930 | USET_ADD_CP_AND_NEXT(sa, NBSP); | |
931 | USET_ADD_CP_AND_NEXT(sa, FIGURESP); | |
932 | USET_ADD_CP_AND_NEXT(sa, NNBSP); | |
b75a7d8f | 933 | |
374ca955 A |
934 | /* add for u_digit() */ |
935 | sa->add(sa->set, U_a); | |
936 | sa->add(sa->set, U_z+1); | |
937 | sa->add(sa->set, U_A); | |
938 | sa->add(sa->set, U_Z+1); | |
73c04bcf A |
939 | sa->add(sa->set, U_FW_a); |
940 | sa->add(sa->set, U_FW_z+1); | |
941 | sa->add(sa->set, U_FW_A); | |
942 | sa->add(sa->set, U_FW_Z+1); | |
943 | ||
944 | /* add for u_isxdigit() */ | |
945 | sa->add(sa->set, U_f+1); | |
946 | sa->add(sa->set, U_F+1); | |
947 | sa->add(sa->set, U_FW_f+1); | |
948 | sa->add(sa->set, U_FW_F+1); | |
b75a7d8f | 949 | |
374ca955 A |
950 | /* add for UCHAR_DEFAULT_IGNORABLE_CODE_POINT what was not added above */ |
951 | sa->add(sa->set, WJ); /* range WJ..NOMDIG */ | |
952 | sa->add(sa->set, 0xfff0); | |
953 | sa->add(sa->set, 0xfffb+1); | |
954 | sa->add(sa->set, 0xe0000); | |
955 | sa->add(sa->set, 0xe0fff+1); | |
b75a7d8f | 956 | |
374ca955 A |
957 | /* add for UCHAR_GRAPHEME_BASE and others */ |
958 | USET_ADD_CP_AND_NEXT(sa, CGJ); | |
73c04bcf | 959 | } |
b75a7d8f | 960 | |
46f4442e | 961 | U_CFUNC void U_EXPORT2 |
73c04bcf A |
962 | upropsvec_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) { |
963 | if(U_FAILURE(*pErrorCode)) { | |
964 | return; | |
965 | } | |
966 | ||
967 | #if !UCHAR_HARDCODE_DATA | |
968 | if(!HAVE_DATA) { | |
969 | *pErrorCode=dataErrorCode; | |
970 | return; | |
971 | } | |
972 | #endif | |
973 | ||
974 | /* add the start code point of each same-value range of the properties vectors trie */ | |
975 | if(propsVectorsColumns>0) { | |
976 | /* if propsVectorsColumns==0 then the properties vectors trie may not be there at all */ | |
977 | utrie_enum(&propsVectorsTrie, NULL, _enumPropertyStartsRange, sa); | |
978 | } | |
b75a7d8f | 979 | } |