]> git.saurik.com Git - apple/cf.git/blob - CFUniChar.c
CF-1151.16.tar.gz
[apple/cf.git] / CFUniChar.c
1 /*
2 * Copyright (c) 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /* CFUniChar.c
25 Copyright (c) 2001-2014, Apple Inc. All rights reserved.
26 Responsibility: Aki Inoue
27 */
28
29 #include <CoreFoundation/CFByteOrder.h>
30 #include "CFInternal.h"
31 #include "CFUniChar.h"
32 #include "CFStringEncodingConverterExt.h"
33 #include "CFUnicodeDecomposition.h"
34 #include "CFUniCharPriv.h"
35 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/param.h>
40 #include <sys/mman.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #endif
44 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
45 #include <mach/mach.h>
46 #endif
47
48 #if DEPLOYMENT_TARGET_WINDOWS
49 extern void _CFGetFrameworkPath(wchar_t *path, int maxLength);
50 #endif
51
52 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
53 #define __kCFCharacterSetDir "/System/Library/CoreServices"
54 #elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD || DEPLOYMENT_TARGET_EMBEDDED_MINI
55 #define __kCFCharacterSetDir "/usr/local/share/CoreFoundation"
56 #elif DEPLOYMENT_TARGET_WINDOWS
57 #define __kCFCharacterSetDir "\\Windows\\CoreFoundation"
58 #endif
59
60 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
61 #define USE_MACHO_SEGMENT 1
62 #endif
63
64 enum {
65 kCFUniCharLastExternalSet = kCFUniCharNewlineCharacterSet,
66 kCFUniCharFirstInternalSet = kCFUniCharCompatibilityDecomposableCharacterSet,
67 kCFUniCharLastInternalSet = kCFUniCharGraphemeExtendCharacterSet,
68 kCFUniCharFirstBitmapSet = kCFUniCharDecimalDigitCharacterSet
69 };
70
71 CF_INLINE uint32_t __CFUniCharMapExternalSetToInternalIndex(uint32_t cset) { return ((kCFUniCharFirstInternalSet <= cset) ? ((cset - kCFUniCharFirstInternalSet) + kCFUniCharLastExternalSet) : cset) - kCFUniCharFirstBitmapSet; }
72 CF_INLINE uint32_t __CFUniCharMapCompatibilitySetID(uint32_t cset) { return ((cset == kCFUniCharControlCharacterSet) ? kCFUniCharControlAndFormatterCharacterSet : (((cset > kCFUniCharLastExternalSet) && (cset < kCFUniCharFirstInternalSet)) ? ((cset - kCFUniCharLastExternalSet) + kCFUniCharFirstInternalSet) : cset)); }
73
74 #if (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED) && USE_MACHO_SEGMENT
75 #include <mach-o/getsect.h>
76 #include <mach-o/dyld.h>
77 #include <mach-o/ldsyms.h>
78
79 extern const void* unicode_csbitmaps_section_start __asm("section$start$__UNICODE$__csbitmaps");
80 extern const void* unicode_csbitmaps_section_end __asm("section$end$__UNICODE$__csbitmaps");
81 extern const void* unicode_properties_section_start __asm("section$start$__UNICODE$__properties");
82 extern const void* unicode_properties_section_end __asm("section$end$__UNICODE$__properties");
83 extern const void* unicode_data_section_start __asm("section$start$__UNICODE$__data");
84 extern const void* unicode_data_section_end __asm("section$end$__UNICODE$__data");
85
86 static const void *__CFGetSectDataPtr(const char *segname, const char *sectname, uint64_t *sizep) {
87 // special case three common sections to have fast access
88 if ( strcmp(segname, "__UNICODE") == 0 ) {
89 if ( strcmp(sectname, "__csbitmaps") == 0) {
90 if (sizep) *sizep = &unicode_csbitmaps_section_end - &unicode_csbitmaps_section_start;
91 return &unicode_csbitmaps_section_start;
92 }
93 else if ( strcmp(sectname, "__properties") == 0 ) {
94 if (sizep) *sizep = &unicode_properties_section_end - &unicode_properties_section_start;
95 return &unicode_properties_section_start;
96 }
97 else if ( strcmp(sectname, "__data") == 0 ) {
98 if (sizep) *sizep = &unicode_data_section_end - &unicode_data_section_start;
99 return &unicode_data_section_start;
100 }
101 }
102
103 uint32_t idx, cnt = _dyld_image_count();
104 for (idx = 0; idx < cnt; idx++) {
105 void *mh = (void *)_dyld_get_image_header(idx);
106 if (mh != &_mh_dylib_header) continue;
107 #if __LP64__
108 const struct section_64 *sect = getsectbynamefromheader_64((struct mach_header_64 *)mh, segname, sectname);
109 #else
110 const struct section *sect = getsectbynamefromheader((struct mach_header *)mh, segname, sectname);
111 #endif
112 if (!sect) break;
113 if (sizep) *sizep = (uint64_t)sect->size;
114 return (char *)sect->addr + _dyld_get_image_vmaddr_slide(idx);
115 }
116 if (sizep) *sizep = 0ULL;
117 return NULL;
118 }
119 #endif
120
121 #if !USE_MACHO_SEGMENT
122
123 // Memory map the file
124
125 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
126 CF_INLINE void __CFUniCharCharacterSetPath(char *cpath) {
127 #elif DEPLOYMENT_TARGET_WINDOWS
128 CF_INLINE void __CFUniCharCharacterSetPath(wchar_t *wpath) {
129 #else
130 #error Unknown or unspecified DEPLOYMENT_TARGET
131 #endif
132 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
133 strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
134 #elif DEPLOYMENT_TARGET_LINUX
135 strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
136 #elif DEPLOYMENT_TARGET_WINDOWS
137 wchar_t frameworkPath[MAXPATHLEN];
138 _CFGetFrameworkPath(frameworkPath, MAXPATHLEN);
139 wcsncpy(wpath, frameworkPath, MAXPATHLEN);
140 wcsncat(wpath, L"\\CoreFoundation.resources\\", MAXPATHLEN - wcslen(wpath));
141 #else
142 strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
143 strlcat(cpath, "/CharacterSets/", MAXPATHLEN);
144 #endif
145 }
146
147 #if DEPLOYMENT_TARGET_WINDOWS
148 #define MAX_BITMAP_STATE 512
149 //
150 // If a string is placed into this array, then it has been previously
151 // determined that the bitmap-file cannot be found. Thus, we make
152 // the assumption it won't be there in future calls and we avoid
153 // hitting the disk un-necessarily. This assumption isn't 100%
154 // correct, as bitmap-files can be added. We would have to re-start
155 // the application in order to pick-up the new bitmap info.
156 //
157 // We should probably re-visit this.
158 //
159 static wchar_t *mappedBitmapState[MAX_BITMAP_STATE];
160 static int __nNumStateEntries = -1;
161 CRITICAL_SECTION __bitmapStateLock = {0};
162
163 bool __GetBitmapStateForName(const wchar_t *bitmapName) {
164 if (NULL == __bitmapStateLock.DebugInfo)
165 InitializeCriticalSection(&__bitmapStateLock);
166 EnterCriticalSection(&__bitmapStateLock);
167 if (__nNumStateEntries >= 0) {
168 for (int i = 0; i < __nNumStateEntries; i++) {
169 if (wcscmp(mappedBitmapState[i], bitmapName) == 0) {
170 LeaveCriticalSection(&__bitmapStateLock);
171 return true;
172 }
173 }
174 }
175 LeaveCriticalSection(&__bitmapStateLock);
176 return false;
177 }
178 void __AddBitmapStateForName(const wchar_t *bitmapName) {
179 if (NULL == __bitmapStateLock.DebugInfo)
180 InitializeCriticalSection(&__bitmapStateLock);
181 EnterCriticalSection(&__bitmapStateLock);
182 __nNumStateEntries++;
183 mappedBitmapState[__nNumStateEntries] = (wchar_t *)malloc((lstrlenW(bitmapName)+1) * sizeof(wchar_t));
184 lstrcpyW(mappedBitmapState[__nNumStateEntries], bitmapName);
185 LeaveCriticalSection(&__bitmapStateLock);
186 }
187 #endif
188
189 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
190 static bool __CFUniCharLoadBytesFromFile(const char *fileName, const void **bytes, int64_t *fileSize) {
191 #elif DEPLOYMENT_TARGET_WINDOWS
192 static bool __CFUniCharLoadBytesFromFile(const wchar_t *fileName, const void **bytes, int64_t *fileSize) {
193 #else
194 #error Unknown or unspecified DEPLOYMENT_TARGET
195 #endif
196 #if DEPLOYMENT_TARGET_WINDOWS
197 HANDLE bitmapFileHandle = NULL;
198 HANDLE mappingHandle = NULL;
199
200 if (__GetBitmapStateForName(fileName)) {
201 // The fileName has been tried in the past, so just return false
202 // and move on.
203 *bytes = NULL;
204 return false;
205 }
206 mappingHandle = OpenFileMappingW(FILE_MAP_READ, TRUE, fileName);
207 if (NULL == mappingHandle) {
208 if ((bitmapFileHandle = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
209 // We tried to get the bitmap file for mapping, but it's not there. Add to list of non-existant bitmap-files so
210 // we don't have to try this again in the future.
211 __AddBitmapStateForName(fileName);
212 return false;
213 }
214 mappingHandle = CreateFileMapping(bitmapFileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
215 CloseHandle(bitmapFileHandle);
216 if (!mappingHandle) return false;
217 }
218
219 *bytes = MapViewOfFileEx(mappingHandle, FILE_MAP_READ, 0, 0, 0, 0);
220
221 if (NULL != fileSize) {
222 MEMORY_BASIC_INFORMATION memoryInfo;
223
224 if (0 == VirtualQueryEx(mappingHandle, *bytes, &memoryInfo, sizeof(memoryInfo))) {
225 *fileSize = 0; // This indicates no checking. Is it right ?
226 } else {
227 *fileSize = memoryInfo.RegionSize;
228 }
229 }
230
231 CloseHandle(mappingHandle);
232
233 return (*bytes ? true : false);
234 #else
235 struct stat statBuf;
236 int fd = -1;
237
238 if ((fd = open(fileName, O_RDONLY, 0)) < 0) {
239 return false;
240 }
241 if (fstat(fd, &statBuf) < 0 || (*bytes = mmap(0, statBuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1) {
242 close(fd);
243 return false;
244 }
245 close(fd);
246
247 if (NULL != fileSize) *fileSize = statBuf.st_size;
248
249 return true;
250 #endif
251 }
252
253 #endif // USE_MACHO_SEGMENT
254
255 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
256 static bool __CFUniCharLoadFile(const char *bitmapName, const void **bytes, int64_t *fileSize) {
257 #elif DEPLOYMENT_TARGET_WINDOWS
258 static bool __CFUniCharLoadFile(const wchar_t *bitmapName, const void **bytes, int64_t *fileSize) {
259 #else
260 #error Unknown or unspecified DEPLOYMENT_TARGET
261 #endif
262 #if USE_MACHO_SEGMENT
263 *bytes = __CFGetSectDataPtr("__UNICODE", bitmapName, NULL);
264
265 if (NULL != fileSize) *fileSize = 0;
266
267 return *bytes ? true : false;
268 #else
269 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
270 char cpath[MAXPATHLEN];
271 __CFUniCharCharacterSetPath(cpath);
272 strlcat(cpath, bitmapName, MAXPATHLEN);
273 Boolean needToFree = false;
274 const char *possiblyFrameworkRootedCPath = CFPathRelativeToAppleFrameworksRoot(cpath, &needToFree);
275 bool result = __CFUniCharLoadBytesFromFile(possiblyFrameworkRootedCPath, bytes, fileSize);
276 if (needToFree) free((void *)possiblyFrameworkRootedCPath);
277 return result;
278 #elif DEPLOYMENT_TARGET_WINDOWS
279 wchar_t wpath[MAXPATHLEN];
280 __CFUniCharCharacterSetPath(wpath);
281 wcsncat(wpath, bitmapName, MAXPATHLEN);
282 return __CFUniCharLoadBytesFromFile(wpath, bytes, fileSize);
283 #else
284 #error Unknown or unspecified DEPLOYMENT_TARGET
285 #endif
286 #endif
287 }
288
289 // Bitmap functions
290 /*
291 Currently unused but left in for symmetry/informative purposes
292 CF_INLINE bool isControl(UTF32Char theChar, uint16_t charset, const void *data) { // ISO Control
293 return (((theChar <= 0x001F) || (theChar >= 0x007F && theChar <= 0x009F)) ? true : false);
294 }*/
295
296 CF_INLINE bool isWhitespace(UTF32Char theChar, uint16_t charset, const void *data) { // Space
297 return (((theChar == 0x0020) || (theChar == 0x0009) || (theChar == 0x00A0) || (theChar == 0x1680) || (theChar >= 0x2000 && theChar <= 0x200B) || (theChar == 0x202F) || (theChar == 0x205F) || (theChar == 0x3000)) ? true : false);
298 }
299
300 CF_INLINE bool isNewline(UTF32Char theChar, uint16_t charset, const void *data) { // White space
301 return (((theChar >= 0x000A && theChar <= 0x000D) || (theChar == 0x0085) || (theChar == 0x2028) || (theChar == 0x2029)) ? true : false);
302 }
303
304 CF_INLINE bool isWhitespaceAndNewline(UTF32Char theChar, uint16_t charset, const void *data) { // White space
305 return ((isWhitespace(theChar, charset, data) || isNewline(theChar, charset, data)) ? true : false);
306 }
307
308 #if USE_MACHO_SEGMENT
309 CF_INLINE bool __CFSimpleFileSizeVerification(const void *bytes, int64_t fileSize) { return true; }
310 #elif 1
311 // <rdar://problem/8961744> __CFSimpleFileSizeVerification is broken
312 static bool __CFSimpleFileSizeVerification(const void *bytes, int64_t fileSize) { return true; }
313 #else
314 static bool __CFSimpleFileSizeVerification(const void *bytes, int64_t fileSize) {
315 bool result = true;
316
317 if (fileSize > 0) {
318 if ((sizeof(uint32_t) * 2) > fileSize) {
319 result = false;
320 } else {
321 uint32_t headerSize = CFSwapInt32BigToHost(*((uint32_t *)((char *)bytes + 4)));
322
323 if ((headerSize < (sizeof(uint32_t) * 4)) || (headerSize > fileSize)) {
324 result = false;
325 } else {
326 const uint32_t *lastElement = (uint32_t *)(((uint8_t *)bytes) + headerSize) - 2;
327
328 if ((headerSize + CFSwapInt32BigToHost(lastElement[0]) + CFSwapInt32BigToHost(lastElement[1])) > headerSize) result = false;
329 }
330 }
331 }
332
333 if (!result) CFLog(kCFLogLevelCritical, CFSTR("File size verification for Unicode database file failed."));
334
335 return result;
336 }
337 #endif // USE_MACHO_SEGMENT
338
339 typedef struct {
340 uint32_t _numPlanes;
341 const uint8_t **_planes;
342 } __CFUniCharBitmapData;
343
344 static char __CFUniCharUnicodeVersionString[8] = {0, 0, 0, 0, 0, 0, 0, 0};
345
346 static uint32_t __CFUniCharNumberOfBitmaps = 0;
347 static __CFUniCharBitmapData *__CFUniCharBitmapDataArray = NULL;
348
349 static CFLock_t __CFUniCharBitmapLock = CFLockInit;
350
351 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
352 #if !defined(CF_UNICHAR_BITMAP_FILE)
353 #if USE_MACHO_SEGMENT
354 #define CF_UNICHAR_BITMAP_FILE "__csbitmaps"
355 #else
356 #define CF_UNICHAR_BITMAP_FILE "/CFCharacterSetBitmaps.bitmap"
357 #endif
358 #endif
359 #elif DEPLOYMENT_TARGET_WINDOWS
360 #if !defined(CF_UNICHAR_BITMAP_FILE)
361 #define CF_UNICHAR_BITMAP_FILE L"CFCharacterSetBitmaps.bitmap"
362 #endif
363 #else
364 #error Unknown or unspecified DEPLOYMENT_TARGET
365 #endif
366
367 static bool __CFUniCharLoadBitmapData(void) {
368 __CFUniCharBitmapData *array;
369 uint32_t headerSize;
370 uint32_t bitmapSize;
371 int numPlanes;
372 uint8_t currentPlane;
373 const void *bytes;
374 const void *bitmapBase;
375 const void *bitmap;
376 int idx, bitmapIndex;
377 int64_t fileSize;
378
379 __CFLock(&__CFUniCharBitmapLock);
380
381 if (__CFUniCharBitmapDataArray || !__CFUniCharLoadFile(CF_UNICHAR_BITMAP_FILE, &bytes, &fileSize) || !__CFSimpleFileSizeVerification(bytes, fileSize)) {
382 __CFUnlock(&__CFUniCharBitmapLock);
383 return false;
384 }
385
386 for (idx = 0;idx < 4 && ((const uint8_t *)bytes)[idx];idx++) {
387 __CFUniCharUnicodeVersionString[idx * 2] = ((const uint8_t *)bytes)[idx];
388 __CFUniCharUnicodeVersionString[idx * 2 + 1] = '.';
389 }
390 __CFUniCharUnicodeVersionString[(idx < 4 ? idx * 2 - 1 : 7)] = '\0';
391
392 headerSize = CFSwapInt32BigToHost(*((uint32_t *)((char *)bytes + 4)));
393
394 bitmapBase = (uint8_t *)bytes + headerSize;
395 bytes = (uint8_t *)bytes + (sizeof(uint32_t) * 2);
396 headerSize -= (sizeof(uint32_t) * 2);
397
398 __CFUniCharNumberOfBitmaps = headerSize / (sizeof(uint32_t) * 2);
399
400 array = (__CFUniCharBitmapData *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__CFUniCharBitmapData) * __CFUniCharNumberOfBitmaps, 0);
401
402 for (idx = 0;idx < (int)__CFUniCharNumberOfBitmaps;idx++) {
403 bitmap = (uint8_t *)bitmapBase + CFSwapInt32BigToHost(*((uint32_t *)bytes)); bytes = (uint8_t *)bytes + sizeof(uint32_t);
404 bitmapSize = CFSwapInt32BigToHost(*((uint32_t *)bytes)); bytes = (uint8_t *)bytes + sizeof(uint32_t);
405
406 numPlanes = bitmapSize / (8 * 1024);
407 numPlanes = *(const uint8_t *)((char *)bitmap + (((numPlanes - 1) * ((8 * 1024) + 1)) - 1)) + 1;
408 array[idx]._planes = (const uint8_t **)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(const void *) * numPlanes, 0);
409 array[idx]._numPlanes = numPlanes;
410
411 currentPlane = 0;
412 for (bitmapIndex = 0;bitmapIndex < numPlanes;bitmapIndex++) {
413 if (bitmapIndex == currentPlane) {
414 array[idx]._planes[bitmapIndex] = (const uint8_t *)bitmap;
415 bitmap = (uint8_t *)bitmap + (8 * 1024);
416 #if defined (__cplusplus)
417 currentPlane = *(((const uint8_t*&)bitmap)++);
418 #else
419 currentPlane = *((const uint8_t *)bitmap++);
420 #endif
421
422 } else {
423 array[idx]._planes[bitmapIndex] = NULL;
424 }
425 }
426 }
427
428 __CFUniCharBitmapDataArray = array;
429
430 __CFUnlock(&__CFUniCharBitmapLock);
431
432 return true;
433 }
434
435 CF_PRIVATE const char *__CFUniCharGetUnicodeVersionString(void) {
436 if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
437 return __CFUniCharUnicodeVersionString;
438 }
439
440 bool CFUniCharIsMemberOf(UTF32Char theChar, uint32_t charset) {
441 charset = __CFUniCharMapCompatibilitySetID(charset);
442
443 switch (charset) {
444 case kCFUniCharWhitespaceCharacterSet:
445 return isWhitespace(theChar, charset, NULL);
446
447 case kCFUniCharWhitespaceAndNewlineCharacterSet:
448 return isWhitespaceAndNewline(theChar, charset, NULL);
449
450 case kCFUniCharNewlineCharacterSet:
451 return isNewline(theChar, charset, NULL);
452
453 default: {
454 uint32_t tableIndex = __CFUniCharMapExternalSetToInternalIndex(charset);
455
456 if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
457
458 if (tableIndex < __CFUniCharNumberOfBitmaps) {
459 __CFUniCharBitmapData *data = __CFUniCharBitmapDataArray + tableIndex;
460 uint8_t planeNo = (theChar >> 16) & 0xFF;
461
462 // The bitmap data for kCFUniCharIllegalCharacterSet is actually LEGAL set less Plane 14 ~ 16
463 if (charset == kCFUniCharIllegalCharacterSet) {
464 if (planeNo == 0x0E) { // Plane 14
465 theChar &= 0xFF;
466 return (((theChar == 0x01) || ((theChar > 0x1F) && (theChar < 0x80))) ? false : true);
467 } else if (planeNo == 0x0F || planeNo == 0x10) { // Plane 15 & 16
468 return ((theChar & 0xFF) > 0xFFFD ? true : false);
469 } else {
470 return (planeNo < data->_numPlanes && data->_planes[planeNo] ? !CFUniCharIsMemberOfBitmap(theChar, data->_planes[planeNo]) : true);
471 }
472 } else if (charset == kCFUniCharControlAndFormatterCharacterSet) {
473 if (planeNo == 0x0E) { // Plane 14
474 theChar &= 0xFF;
475 return (((theChar == 0x01) || ((theChar > 0x1F) && (theChar < 0x80))) ? true : false);
476 } else {
477 return (planeNo < data->_numPlanes && data->_planes[planeNo] ? CFUniCharIsMemberOfBitmap(theChar, data->_planes[planeNo]) : false);
478 }
479 } else {
480 return (planeNo < data->_numPlanes && data->_planes[planeNo] ? CFUniCharIsMemberOfBitmap(theChar, data->_planes[planeNo]) : false);
481 }
482 }
483 return false;
484 }
485 }
486 }
487
488 const uint8_t *CFUniCharGetBitmapPtrForPlane(uint32_t charset, uint32_t plane) {
489 if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
490
491 charset = __CFUniCharMapCompatibilitySetID(charset);
492
493 if ((charset > kCFUniCharWhitespaceAndNewlineCharacterSet) && (charset != kCFUniCharIllegalCharacterSet) && (charset != kCFUniCharNewlineCharacterSet)) {
494 uint32_t tableIndex = __CFUniCharMapExternalSetToInternalIndex(charset);
495
496 if (tableIndex < __CFUniCharNumberOfBitmaps) {
497 __CFUniCharBitmapData *data = __CFUniCharBitmapDataArray + tableIndex;
498
499 return (plane < data->_numPlanes ? data->_planes[plane] : NULL);
500 }
501 }
502 return NULL;
503 }
504
505 CF_PRIVATE uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t plane, void *bitmap, bool isInverted) {
506 const uint8_t *src = CFUniCharGetBitmapPtrForPlane(charset, plane);
507 int numBytes = (8 * 1024);
508
509 if (src) {
510 if (isInverted) {
511 #if defined (__cplusplus)
512 while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = ~(*(src++));
513 #else
514 while (numBytes-- > 0) *((uint8_t *)bitmap++) = ~(*(src++));
515 #endif
516 } else {
517 #if defined (__cplusplus)
518 while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = *(src++);
519 #else
520 while (numBytes-- > 0) *((uint8_t *)bitmap++) = *(src++);
521 #endif
522 }
523 return kCFUniCharBitmapFilled;
524 } else if (charset == kCFUniCharIllegalCharacterSet) {
525 __CFUniCharBitmapData *data = __CFUniCharBitmapDataArray + __CFUniCharMapExternalSetToInternalIndex(__CFUniCharMapCompatibilitySetID(charset));
526
527 if (plane < data->_numPlanes && (src = data->_planes[plane])) {
528 if (isInverted) {
529 #if defined (__cplusplus)
530 while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = *(src++);
531 #else
532 while (numBytes-- > 0) *((uint8_t *)bitmap++) = *(src++);
533 #endif
534 } else {
535 #if defined (__cplusplus)
536 while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = ~(*(src++));
537 #else
538 while (numBytes-- > 0) *((uint8_t *)bitmap++) = ~(*(src++));
539 #endif
540 }
541 return kCFUniCharBitmapFilled;
542 } else if (plane == 0x0E) { // Plane 14
543 int idx;
544 uint8_t asciiRange = (isInverted ? (uint8_t)0xFF : (uint8_t)0);
545 uint8_t otherRange = (isInverted ? (uint8_t)0 : (uint8_t)0xFF);
546
547 #if defined (__cplusplus)
548 *(((uint8_t *&)bitmap)++) = 0x02; // UE0001 LANGUAGE TAG
549 #else
550 *((uint8_t *)bitmap++) = 0x02; // UE0001 LANGUAGE TAG
551 #endif
552 for (idx = 1;idx < numBytes;idx++) {
553 #if defined (__cplusplus)
554 *(((uint8_t *&)bitmap)++) = ((idx >= (0x20 / 8) && (idx < (0x80 / 8))) ? asciiRange : otherRange);
555 #else
556 *((uint8_t *)bitmap++) = ((idx >= (0x20 / 8) && (idx < (0x80 / 8))) ? asciiRange : otherRange);
557 #endif
558 }
559 return kCFUniCharBitmapFilled;
560 } else if (plane == 0x0F || plane == 0x10) { // Plane 15 & 16
561 uint32_t value = (isInverted ? ~0 : 0);
562 numBytes /= 4; // for 32bit
563
564 while (numBytes-- > 0) {
565 *((uint32_t *)bitmap) = value;
566 #if defined (__cplusplus)
567 bitmap = (uint8_t *)bitmap + sizeof(uint32_t);
568 #else
569 bitmap += sizeof(uint32_t);
570 #endif
571 }
572 *(((uint8_t *)bitmap) - 5) = (isInverted ? 0x3F : 0xC0); // 0xFFFE & 0xFFFF
573 return kCFUniCharBitmapFilled;
574 }
575 return (isInverted ? kCFUniCharBitmapEmpty : kCFUniCharBitmapAll);
576 } else if ((charset < kCFUniCharDecimalDigitCharacterSet) || (charset == kCFUniCharNewlineCharacterSet)) {
577 if (plane) return (isInverted ? kCFUniCharBitmapAll : kCFUniCharBitmapEmpty);
578
579 uint8_t *bitmapBase = (uint8_t *)bitmap;
580 CFIndex idx;
581 uint8_t nonFillValue = (isInverted ? (uint8_t)0xFF : (uint8_t)0);
582
583 #if defined (__cplusplus)
584 while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = nonFillValue;
585 #else
586 while (numBytes-- > 0) *((uint8_t *)bitmap++) = nonFillValue;
587 #endif
588
589 if ((charset == kCFUniCharWhitespaceAndNewlineCharacterSet) || (charset == kCFUniCharNewlineCharacterSet)) {
590 const UniChar newlines[] = {0x000A, 0x000B, 0x000C, 0x000D, 0x0085, 0x2028, 0x2029};
591
592 for (idx = 0;idx < (int)(sizeof(newlines) / sizeof(*newlines)); idx++) {
593 if (isInverted) {
594 CFUniCharRemoveCharacterFromBitmap(newlines[idx], bitmapBase);
595 } else {
596 CFUniCharAddCharacterToBitmap(newlines[idx], bitmapBase);
597 }
598 }
599
600 if (charset == kCFUniCharNewlineCharacterSet) return kCFUniCharBitmapFilled;
601 }
602
603 if (isInverted) {
604 CFUniCharRemoveCharacterFromBitmap(0x0009, bitmapBase);
605 CFUniCharRemoveCharacterFromBitmap(0x0020, bitmapBase);
606 CFUniCharRemoveCharacterFromBitmap(0x00A0, bitmapBase);
607 CFUniCharRemoveCharacterFromBitmap(0x1680, bitmapBase);
608 CFUniCharRemoveCharacterFromBitmap(0x202F, bitmapBase);
609 CFUniCharRemoveCharacterFromBitmap(0x205F, bitmapBase);
610 CFUniCharRemoveCharacterFromBitmap(0x3000, bitmapBase);
611 } else {
612 CFUniCharAddCharacterToBitmap(0x0009, bitmapBase);
613 CFUniCharAddCharacterToBitmap(0x0020, bitmapBase);
614 CFUniCharAddCharacterToBitmap(0x00A0, bitmapBase);
615 CFUniCharAddCharacterToBitmap(0x1680, bitmapBase);
616 CFUniCharAddCharacterToBitmap(0x202F, bitmapBase);
617 CFUniCharAddCharacterToBitmap(0x205F, bitmapBase);
618 CFUniCharAddCharacterToBitmap(0x3000, bitmapBase);
619 }
620
621 for (idx = 0x2000;idx <= 0x200B;idx++) {
622 if (isInverted) {
623 CFUniCharRemoveCharacterFromBitmap(idx, bitmapBase);
624 } else {
625 CFUniCharAddCharacterToBitmap(idx, bitmapBase);
626 }
627 }
628 return kCFUniCharBitmapFilled;
629 }
630 return (isInverted ? kCFUniCharBitmapAll : kCFUniCharBitmapEmpty);
631 }
632
633 CF_PRIVATE uint32_t CFUniCharGetNumberOfPlanes(uint32_t charset) {
634 if ((charset == kCFUniCharControlCharacterSet) || (charset == kCFUniCharControlAndFormatterCharacterSet)) {
635 return 15; // 0 to 14
636 } else if (charset < kCFUniCharDecimalDigitCharacterSet) {
637 return 1;
638 } else if (charset == kCFUniCharIllegalCharacterSet) {
639 return 17;
640 } else {
641 uint32_t numPlanes;
642
643 if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
644
645 numPlanes = __CFUniCharBitmapDataArray[__CFUniCharMapExternalSetToInternalIndex(__CFUniCharMapCompatibilitySetID(charset))]._numPlanes;
646
647 return numPlanes;
648 }
649 }
650
651 // Mapping data loading
652 static const void **__CFUniCharMappingTables = NULL;
653
654 static CFLock_t __CFUniCharMappingTableLock = CFLockInit;
655
656 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
657 #if __CF_BIG_ENDIAN__
658 #if USE_MACHO_SEGMENT
659 #define MAPPING_TABLE_FILE "__data"
660 #else
661 #define MAPPING_TABLE_FILE "/CFUnicodeData-B.mapping"
662 #endif
663 #else
664 #if USE_MACHO_SEGMENT
665 #define MAPPING_TABLE_FILE "__data"
666 #else
667 #define MAPPING_TABLE_FILE "/CFUnicodeData-L.mapping"
668 #endif
669 #endif
670 #elif DEPLOYMENT_TARGET_WINDOWS
671 #if __CF_BIG_ENDIAN__
672 #if USE_MACHO_SEGMENT
673 #define MAPPING_TABLE_FILE "__data"
674 #else
675 #define MAPPING_TABLE_FILE L"CFUnicodeData-B.mapping"
676 #endif
677 #else
678 #if USE_MACHO_SEGMENT
679 #define MAPPING_TABLE_FILE "__data"
680 #else
681 #define MAPPING_TABLE_FILE L"CFUnicodeData-L.mapping"
682 #endif
683 #endif
684 #else
685 #error Unknown or unspecified DEPLOYMENT_TARGET
686 #endif
687
688 CF_PRIVATE const void *CFUniCharGetMappingData(uint32_t type) {
689
690 __CFLock(&__CFUniCharMappingTableLock);
691
692 if (NULL == __CFUniCharMappingTables) {
693 const void *bytes;
694 const void *bodyBase;
695 int headerSize;
696 int idx, count;
697 int64_t fileSize;
698
699 if (!__CFUniCharLoadFile(MAPPING_TABLE_FILE, &bytes, &fileSize) || !__CFSimpleFileSizeVerification(bytes, fileSize)) {
700 __CFUnlock(&__CFUniCharMappingTableLock);
701 return NULL;
702 }
703
704 #if defined (__cplusplus)
705 bytes = (uint8_t *)bytes + 4; // Skip Unicode version
706 headerSize = *((uint8_t *)bytes); bytes = (uint8_t *)bytes + sizeof(uint32_t);
707 #else
708 bytes += 4; // Skip Unicode version
709 headerSize = *((uint32_t *)bytes); bytes += sizeof(uint32_t);
710 #endif
711 headerSize -= (sizeof(uint32_t) * 2);
712 bodyBase = (char *)bytes + headerSize;
713
714 count = headerSize / sizeof(uint32_t);
715
716 __CFUniCharMappingTables = (const void **)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(const void *) * count, 0);
717
718 for (idx = 0;idx < count;idx++) {
719 #if defined (__cplusplus)
720 __CFUniCharMappingTables[idx] = (char *)bodyBase + *((uint32_t *)bytes); bytes = (uint8_t *)bytes + sizeof(uint32_t);
721 #else
722 __CFUniCharMappingTables[idx] = (char *)bodyBase + *((uint32_t *)bytes); bytes += sizeof(uint32_t);
723 #endif
724 }
725 }
726
727 __CFUnlock(&__CFUniCharMappingTableLock);
728
729 return __CFUniCharMappingTables[type];
730 }
731
732 // Case mapping functions
733 #define DO_SPECIAL_CASE_MAPPING 1
734
735 static uint32_t *__CFUniCharCaseMappingTableCounts = NULL;
736 static uint32_t **__CFUniCharCaseMappingTable = NULL;
737 static const uint32_t **__CFUniCharCaseMappingExtraTable = NULL;
738
739 typedef struct {
740 uint32_t _key;
741 uint32_t _value;
742 } __CFUniCharCaseMappings;
743
744 /* Binary searches CFStringEncodingUnicodeTo8BitCharMap */
745 static uint32_t __CFUniCharGetMappedCase(const __CFUniCharCaseMappings *theTable, uint32_t numElem, UTF32Char character) {
746 const __CFUniCharCaseMappings *p, *q, *divider;
747
748 if ((character < theTable[0]._key) || (character > theTable[numElem-1]._key)) {
749 return 0;
750 }
751 p = theTable;
752 q = p + (numElem-1);
753 while (p <= q) {
754 divider = p + ((q - p) >> 1); /* divide by 2 */
755 if (character < divider->_key) { q = divider - 1; }
756 else if (character > divider->_key) { p = divider + 1; }
757 else { return divider->_value; }
758 }
759 return 0;
760 }
761
762 #define NUM_CASE_MAP_DATA (kCFUniCharCaseFold + 1)
763
764 static bool __CFUniCharLoadCaseMappingTable(void) {
765 uint32_t *countArray;
766 int idx;
767
768 if (NULL == __CFUniCharMappingTables) (void)CFUniCharGetMappingData(kCFUniCharToLowercase);
769 if (NULL == __CFUniCharMappingTables) return false;
770
771 __CFLock(&__CFUniCharMappingTableLock);
772
773 if (__CFUniCharCaseMappingTableCounts) {
774 __CFUnlock(&__CFUniCharMappingTableLock);
775 return true;
776 }
777
778 countArray = (uint32_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(uint32_t) * NUM_CASE_MAP_DATA + sizeof(uint32_t *) * NUM_CASE_MAP_DATA * 2, 0);
779 __CFUniCharCaseMappingTable = (uint32_t **)((char *)countArray + sizeof(uint32_t) * NUM_CASE_MAP_DATA);
780 __CFUniCharCaseMappingExtraTable = (const uint32_t **)__CFUniCharCaseMappingTable + NUM_CASE_MAP_DATA;
781
782 for (idx = 0;idx < NUM_CASE_MAP_DATA;idx++) {
783 countArray[idx] = *((uint32_t *)__CFUniCharMappingTables[idx]) / (sizeof(uint32_t) * 2);
784 __CFUniCharCaseMappingTable[idx] = ((uint32_t *)__CFUniCharMappingTables[idx]) + 1;
785 __CFUniCharCaseMappingExtraTable[idx] = (const uint32_t *)((char *)__CFUniCharCaseMappingTable[idx] + *((uint32_t *)__CFUniCharMappingTables[idx]));
786 }
787
788 __CFUniCharCaseMappingTableCounts = countArray;
789
790 __CFUnlock(&__CFUniCharMappingTableLock);
791 return true;
792 }
793
794 #if __CF_BIG_ENDIAN__
795 #define TURKISH_LANG_CODE (0x7472) // tr
796 #define LITHUANIAN_LANG_CODE (0x6C74) // lt
797 #define AZERI_LANG_CODE (0x617A) // az
798 #define DUTCH_LANG_CODE (0x6E6C) // nl
799 #define GREEK_LANG_CODE (0x656C) // el
800 #else
801 #define TURKISH_LANG_CODE (0x7274) // tr
802 #define LITHUANIAN_LANG_CODE (0x746C) // lt
803 #define AZERI_LANG_CODE (0x7A61) // az
804 #define DUTCH_LANG_CODE (0x6C6E) // nl
805 #define GREEK_LANG_CODE (0x6C65) // el
806 #endif
807
808 CFIndex CFUniCharMapCaseTo(UTF32Char theChar, UTF16Char *convertedChar, CFIndex maxLength, uint32_t ctype, uint32_t flags, const uint8_t *langCode) {
809 __CFUniCharBitmapData *data;
810 uint8_t planeNo = (theChar >> 16) & 0xFF;
811
812 caseFoldRetry:
813
814 #if DO_SPECIAL_CASE_MAPPING
815 if (flags & kCFUniCharCaseMapFinalSigma) {
816 if (theChar == 0x03A3) { // Final sigma
817 *convertedChar = (ctype == kCFUniCharToLowercase ? 0x03C2 : 0x03A3);
818 return 1;
819 }
820 }
821
822 if (langCode) {
823 if (flags & kCFUniCharCaseMapGreekTonos) { // localized Greek uppercasing
824 if (theChar == 0x0301) { // GREEK TONOS
825 return 0;
826 } else if (theChar == 0x0344) {// COMBINING GREEK DIALYTIKA TONOS
827 *convertedChar = 0x0308; // COMBINING GREEK DIALYTIKA
828 return 1;
829 } else if (CFUniCharIsMemberOf(theChar, kCFUniCharDecomposableCharacterSet)) {
830 UTF32Char buffer[MAX_DECOMPOSED_LENGTH];
831 CFIndex length = CFUniCharDecomposeCharacter(theChar, buffer, MAX_DECOMPOSED_LENGTH);
832
833 if (length > 1) {
834 UTF32Char *characters = buffer + 1;
835 UTF32Char *tail = buffer + length;
836
837 while (characters < tail) {
838 if (*characters == 0x0301) break;
839 ++characters;
840 }
841
842 if (characters < tail) { // found a tonos
843 CFIndex convertedLength = CFUniCharMapCaseTo(*buffer, convertedChar, maxLength, ctype, 0, langCode);
844
845 if (convertedLength == 0) {
846 *convertedChar = (UTF16Char)*buffer;
847 convertedLength = 1;
848 }
849
850 characters = buffer + 1;
851
852 while (characters < tail) {
853 if (*characters != 0x0301) { // not tonos
854 if (*characters < 0x10000) { // BMP
855 convertedChar[convertedLength] = (UTF16Char)*characters;
856 ++convertedLength;
857 } else {
858 UTF32Char character = *characters - 0x10000;
859 convertedChar[convertedLength++] = (UTF16Char)((character >> 10) + 0xD800UL);
860 convertedChar[convertedLength++] = (UTF16Char)((character & 0x3FF) + 0xDC00UL);
861 }
862 }
863 ++characters;
864 }
865
866 return convertedLength;
867 }
868 }
869 }
870 }
871 switch (*(uint16_t *)langCode) {
872 case LITHUANIAN_LANG_CODE:
873 if (theChar == 0x0307 && (flags & kCFUniCharCaseMapAfter_i)) {
874 return 0;
875 } else if (ctype == kCFUniCharToLowercase) {
876 if (flags & kCFUniCharCaseMapMoreAbove) {
877 switch (theChar) {
878 case 0x0049: // LATIN CAPITAL LETTER I
879 *(convertedChar++) = 0x0069;
880 *(convertedChar++) = 0x0307;
881 return 2;
882
883 case 0x004A: // LATIN CAPITAL LETTER J
884 *(convertedChar++) = 0x006A;
885 *(convertedChar++) = 0x0307;
886 return 2;
887
888 case 0x012E: // LATIN CAPITAL LETTER I WITH OGONEK
889 *(convertedChar++) = 0x012F;
890 *(convertedChar++) = 0x0307;
891 return 2;
892
893 default: break;
894 }
895 }
896 switch (theChar) {
897 case 0x00CC: // LATIN CAPITAL LETTER I WITH GRAVE
898 *(convertedChar++) = 0x0069;
899 *(convertedChar++) = 0x0307;
900 *(convertedChar++) = 0x0300;
901 return 3;
902
903 case 0x00CD: // LATIN CAPITAL LETTER I WITH ACUTE
904 *(convertedChar++) = 0x0069;
905 *(convertedChar++) = 0x0307;
906 *(convertedChar++) = 0x0301;
907 return 3;
908
909 case 0x0128: // LATIN CAPITAL LETTER I WITH TILDE
910 *(convertedChar++) = 0x0069;
911 *(convertedChar++) = 0x0307;
912 *(convertedChar++) = 0x0303;
913 return 3;
914
915 default: break;
916 }
917 }
918 break;
919
920 case TURKISH_LANG_CODE:
921 case AZERI_LANG_CODE:
922 if ((theChar == 0x0049) || (theChar == 0x0131)) { // LATIN CAPITAL LETTER I & LATIN SMALL LETTER DOTLESS I
923 *convertedChar = (((ctype == kCFUniCharToLowercase) || (ctype == kCFUniCharCaseFold)) ? ((kCFUniCharCaseMapMoreAbove & flags) ? 0x0069 : 0x0131) : 0x0049);
924 return 1;
925 } else if ((theChar == 0x0069) || (theChar == 0x0130)) { // LATIN SMALL LETTER I & LATIN CAPITAL LETTER I WITH DOT ABOVE
926 *convertedChar = (((ctype == kCFUniCharToLowercase) || (ctype == kCFUniCharCaseFold)) ? 0x0069 : 0x0130);
927 return 1;
928 } else if (theChar == 0x0307 && (kCFUniCharCaseMapAfter_i & flags)) { // COMBINING DOT ABOVE AFTER_i
929 if (ctype == kCFUniCharToLowercase) {
930 return 0;
931 } else {
932 *convertedChar = 0x0307;
933 return 1;
934 }
935 }
936 break;
937
938 case DUTCH_LANG_CODE:
939 if ((theChar == 0x004A) || (theChar == 0x006A)) {
940 *convertedChar = (((ctype == kCFUniCharToUppercase) || (ctype == kCFUniCharToTitlecase) || (kCFUniCharCaseMapDutchDigraph & flags)) ? 0x004A : 0x006A);
941 return 1;
942 }
943 break;
944
945 default: break;
946 }
947 }
948 #endif // DO_SPECIAL_CASE_MAPPING
949
950 if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
951
952 data = __CFUniCharBitmapDataArray + __CFUniCharMapExternalSetToInternalIndex(__CFUniCharMapCompatibilitySetID(ctype + kCFUniCharHasNonSelfLowercaseCharacterSet));
953
954 if (planeNo < data->_numPlanes && data->_planes[planeNo] && CFUniCharIsMemberOfBitmap(theChar, data->_planes[planeNo]) && (__CFUniCharCaseMappingTableCounts || __CFUniCharLoadCaseMappingTable())) {
955 uint32_t value = __CFUniCharGetMappedCase((const __CFUniCharCaseMappings *)__CFUniCharCaseMappingTable[ctype], __CFUniCharCaseMappingTableCounts[ctype], theChar);
956
957 if (!value && ctype == kCFUniCharToTitlecase) {
958 value = __CFUniCharGetMappedCase((const __CFUniCharCaseMappings *)__CFUniCharCaseMappingTable[kCFUniCharToUppercase], __CFUniCharCaseMappingTableCounts[kCFUniCharToUppercase], theChar);
959 if (value) ctype = kCFUniCharToUppercase;
960 }
961
962 if (value) {
963 CFIndex count = CFUniCharConvertFlagToCount(value);
964
965 if (count == 1) {
966 if (value & kCFUniCharNonBmpFlag) {
967 if (maxLength > 1) {
968 value = (value & 0xFFFFFF) - 0x10000;
969 *(convertedChar++) = (UTF16Char)(value >> 10) + 0xD800UL;
970 *(convertedChar++) = (UTF16Char)(value & 0x3FF) + 0xDC00UL;
971 return 2;
972 }
973 } else {
974 *convertedChar = (UTF16Char)value;
975 return 1;
976 }
977 } else if (count < maxLength) {
978 const uint32_t *extraMapping = __CFUniCharCaseMappingExtraTable[ctype] + (value & 0xFFFFFF);
979
980 if (value & kCFUniCharNonBmpFlag) {
981 CFIndex copiedLen = 0;
982
983 while (count-- > 0) {
984 value = *(extraMapping++);
985 if (value > 0xFFFF) {
986 if (copiedLen + 2 >= maxLength) break;
987 value = (value & 0xFFFFFF) - 0x10000;
988 convertedChar[copiedLen++] = (UTF16Char)(value >> 10) + 0xD800UL;
989 convertedChar[copiedLen++] = (UTF16Char)(value & 0x3FF) + 0xDC00UL;
990 } else {
991 if (copiedLen + 1 >= maxLength) break;
992 convertedChar[copiedLen++] = value;
993 }
994 }
995 if (!count) return copiedLen;
996 } else {
997 CFIndex idx;
998
999 for (idx = 0;idx < count;idx++) *(convertedChar++) = (UTF16Char)*(extraMapping++);
1000 return count;
1001 }
1002 }
1003 }
1004 } else if (ctype == kCFUniCharCaseFold) {
1005 ctype = kCFUniCharToLowercase;
1006 goto caseFoldRetry;
1007 }
1008
1009 if (theChar > 0xFFFF) { // non-BMP
1010 theChar = (theChar & 0xFFFFFF) - 0x10000;
1011 *(convertedChar++) = (UTF16Char)(theChar >> 10) + 0xD800UL;
1012 *(convertedChar++) = (UTF16Char)(theChar & 0x3FF) + 0xDC00UL;
1013 return 2;
1014 } else {
1015 *convertedChar = theChar;
1016 return 1;
1017 }
1018 }
1019
1020 CFIndex CFUniCharMapTo(UniChar theChar, UniChar *convertedChar, CFIndex maxLength, uint16_t ctype, uint32_t flags) {
1021 if (ctype == kCFUniCharCaseFold + 1) { // kCFUniCharDecompose
1022 if (CFUniCharIsDecomposableCharacter(theChar, false)) {
1023 UTF32Char buffer[MAX_DECOMPOSED_LENGTH];
1024 CFIndex usedLength = CFUniCharDecomposeCharacter(theChar, buffer, MAX_DECOMPOSED_LENGTH);
1025 CFIndex idx;
1026
1027 for (idx = 0;idx < usedLength;idx++) *(convertedChar++) = buffer[idx];
1028 return usedLength;
1029 } else {
1030 *convertedChar = theChar;
1031 return 1;
1032 }
1033 } else {
1034 return CFUniCharMapCaseTo(theChar, convertedChar, maxLength, ctype, flags, NULL);
1035 }
1036 }
1037
1038 CF_INLINE bool __CFUniCharIsMoreAbove(UTF16Char *buffer, CFIndex length) {
1039 UTF32Char currentChar;
1040 uint32_t property;
1041
1042 while (length-- > 0) {
1043 currentChar = *(buffer)++;
1044 if (CFUniCharIsSurrogateHighCharacter(currentChar) && (length > 0) && CFUniCharIsSurrogateLowCharacter(*(buffer + 1))) {
1045 currentChar = CFUniCharGetLongCharacterForSurrogatePair(currentChar, *(buffer++));
1046 --length;
1047 }
1048 if (!CFUniCharIsMemberOf(currentChar, kCFUniCharNonBaseCharacterSet)) break;
1049
1050 property = CFUniCharGetCombiningPropertyForCharacter(currentChar, (const uint8_t *)CFUniCharGetUnicodePropertyDataForPlane(kCFUniCharCombiningProperty, (currentChar >> 16) & 0xFF));
1051
1052 if (property == 230) return true; // Above priority
1053 }
1054 return false;
1055 }
1056
1057 CF_INLINE bool __CFUniCharIsAfter_i(UTF16Char *buffer, CFIndex length) {
1058 UTF32Char currentChar = 0;
1059 uint32_t property;
1060 UTF32Char decomposed[MAX_DECOMPOSED_LENGTH];
1061 CFIndex decompLength;
1062 CFIndex idx;
1063
1064 if (length < 1) return 0;
1065
1066 buffer += length;
1067 while (length-- > 1) {
1068 currentChar = *(--buffer);
1069 if (CFUniCharIsSurrogateLowCharacter(currentChar)) {
1070 if ((length > 1) && CFUniCharIsSurrogateHighCharacter(*(buffer - 1))) {
1071 currentChar = CFUniCharGetLongCharacterForSurrogatePair(*(--buffer), currentChar);
1072 --length;
1073 } else {
1074 break;
1075 }
1076 }
1077 if (!CFUniCharIsMemberOf(currentChar, kCFUniCharNonBaseCharacterSet)) break;
1078
1079 property = CFUniCharGetCombiningPropertyForCharacter(currentChar, (const uint8_t *)CFUniCharGetUnicodePropertyDataForPlane(kCFUniCharCombiningProperty, (currentChar >> 16) & 0xFF));
1080
1081 if (property == 230) return false; // Above priority
1082 }
1083 if (length == 0) {
1084 currentChar = *(--buffer);
1085 } else if (CFUniCharIsSurrogateLowCharacter(currentChar) && CFUniCharIsSurrogateHighCharacter(*(--buffer))) {
1086 currentChar = CFUniCharGetLongCharacterForSurrogatePair(*buffer, currentChar);
1087 }
1088
1089 decompLength = CFUniCharDecomposeCharacter(currentChar, decomposed, MAX_DECOMPOSED_LENGTH);
1090 currentChar = *decomposed;
1091
1092
1093 for (idx = 1;idx < decompLength;idx++) {
1094 currentChar = decomposed[idx];
1095 property = CFUniCharGetCombiningPropertyForCharacter(currentChar, (const uint8_t *)CFUniCharGetUnicodePropertyDataForPlane(kCFUniCharCombiningProperty, (currentChar >> 16) & 0xFF));
1096
1097 if (property == 230) return false; // Above priority
1098 }
1099 return true;
1100 }
1101
1102 CF_PRIVATE uint32_t CFUniCharGetConditionalCaseMappingFlags(UTF32Char theChar, UTF16Char *buffer, CFIndex currentIndex, CFIndex length, uint32_t type, const uint8_t *langCode, uint32_t lastFlags) {
1103 if (theChar == 0x03A3) { // GREEK CAPITAL LETTER SIGMA
1104 if ((type == kCFUniCharToLowercase) && (currentIndex > 0)) {
1105 UTF16Char *start = buffer;
1106 UTF16Char *end = buffer + length;
1107 UTF32Char otherChar;
1108
1109 // First check if we're after a cased character
1110 buffer += (currentIndex - 1);
1111 while (start <= buffer) {
1112 otherChar = *(buffer--);
1113 if (CFUniCharIsSurrogateLowCharacter(otherChar) && (start <= buffer) && CFUniCharIsSurrogateHighCharacter(*buffer)) {
1114 otherChar = CFUniCharGetLongCharacterForSurrogatePair(*(buffer--), otherChar);
1115 }
1116 if (!CFUniCharIsMemberOf(otherChar, kCFUniCharCaseIgnorableCharacterSet)) {
1117 if (!CFUniCharIsMemberOf(otherChar, kCFUniCharUppercaseLetterCharacterSet) && !CFUniCharIsMemberOf(otherChar, kCFUniCharLowercaseLetterCharacterSet)) return 0; // Uppercase set contains titlecase
1118 break;
1119 }
1120 }
1121
1122 // Next check if we're before a cased character
1123 buffer = start + currentIndex + 1;
1124 while (buffer < end) {
1125 otherChar = *(buffer++);
1126 if (CFUniCharIsSurrogateHighCharacter(otherChar) && (buffer < end) && CFUniCharIsSurrogateLowCharacter(*buffer)) {
1127 otherChar = CFUniCharGetLongCharacterForSurrogatePair(otherChar, *(buffer++));
1128 }
1129 if (!CFUniCharIsMemberOf(otherChar, kCFUniCharCaseIgnorableCharacterSet)) {
1130 if (CFUniCharIsMemberOf(otherChar, kCFUniCharUppercaseLetterCharacterSet) || CFUniCharIsMemberOf(otherChar, kCFUniCharLowercaseLetterCharacterSet)) return 0; // Uppercase set contains titlecase
1131 break;
1132 }
1133 }
1134 return kCFUniCharCaseMapFinalSigma;
1135 }
1136 } else if (langCode) {
1137 if (*((const uint16_t *)langCode) == LITHUANIAN_LANG_CODE) {
1138 if ((theChar == 0x0307) && ((kCFUniCharCaseMapAfter_i|kCFUniCharCaseMapMoreAbove) & lastFlags) == (kCFUniCharCaseMapAfter_i|kCFUniCharCaseMapMoreAbove)) {
1139 return (__CFUniCharIsAfter_i(buffer, currentIndex) ? kCFUniCharCaseMapAfter_i : 0);
1140 } else if (type == kCFUniCharToLowercase) {
1141 if ((theChar == 0x0049) || (theChar == 0x004A) || (theChar == 0x012E)) {
1142 ++currentIndex;
1143 return (__CFUniCharIsMoreAbove(buffer + currentIndex, length - currentIndex) ? kCFUniCharCaseMapMoreAbove : 0);
1144 }
1145 } else if ((theChar == 'i') || (theChar == 'j')) {
1146 ++currentIndex;
1147 return (__CFUniCharIsMoreAbove(buffer + currentIndex, length - currentIndex) ? (kCFUniCharCaseMapAfter_i|kCFUniCharCaseMapMoreAbove) : 0);
1148 }
1149 } else if ((*((const uint16_t *)langCode) == TURKISH_LANG_CODE) || (*((const uint16_t *)langCode) == AZERI_LANG_CODE)) {
1150 if (type == kCFUniCharToLowercase) {
1151 if (theChar == 0x0307) {
1152 return (kCFUniCharCaseMapMoreAbove & lastFlags ? kCFUniCharCaseMapAfter_i : 0);
1153 } else if (theChar == 0x0049) {
1154 return (((++currentIndex < length) && (buffer[currentIndex] == 0x0307)) ? kCFUniCharCaseMapMoreAbove : 0);
1155 }
1156 }
1157 } else if (*((const uint16_t *)langCode) == DUTCH_LANG_CODE) {
1158 if (kCFUniCharCaseMapDutchDigraph & lastFlags) {
1159 return (((theChar == 0x006A) || (theChar == 0x004A)) ? kCFUniCharCaseMapDutchDigraph : 0);
1160 } else {
1161 if ((type == kCFUniCharToTitlecase) && ((theChar == 0x0069) || (theChar == 0x0049))) {
1162 return (((++currentIndex < length) && ((buffer[currentIndex] == 0x006A) || (buffer[currentIndex] == 0x004A))) ? kCFUniCharCaseMapDutchDigraph : 0);
1163 }
1164 }
1165 }
1166
1167 if (kCFUniCharCaseMapGreekTonos & lastFlags) { // still searching for tonos
1168 if (CFUniCharIsMemberOf(theChar, kCFUniCharNonBaseCharacterSet)) {
1169 return kCFUniCharCaseMapGreekTonos;
1170 }
1171 }
1172 if (((theChar >= 0x0370) && (theChar < 0x0400)) || ((theChar >= 0x1F00) && (theChar < 0x2000))) { // Greek/Coptic & Greek extended ranges
1173 if ((type == kCFUniCharToUppercase) && (CFUniCharIsMemberOf(theChar, kCFUniCharLetterCharacterSet))) return kCFUniCharCaseMapGreekTonos;
1174 }
1175 }
1176 return 0;
1177 }
1178
1179 // Unicode property database
1180 static __CFUniCharBitmapData *__CFUniCharUnicodePropertyTable = NULL;
1181 static int __CFUniCharUnicodePropertyTableCount = 0;
1182
1183 static CFLock_t __CFUniCharPropTableLock = CFLockInit;
1184
1185 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
1186 #if USE_MACHO_SEGMENT
1187 #define PROP_DB_FILE "__properties"
1188 #else
1189 #define PROP_DB_FILE "/CFUniCharPropertyDatabase.data"
1190 #endif
1191 #elif DEPLOYMENT_TARGET_WINDOWS
1192 #if USE_MACHO_SEGMENT
1193 #define PROP_DB_FILE "__properties"
1194 #else
1195 #define PROP_DB_FILE L"CFUniCharPropertyDatabase.data"
1196 #endif
1197 #else
1198 #error Unknown or unspecified DEPLOYMENT_TARGET
1199 #endif
1200
1201 const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint32_t plane) {
1202
1203 __CFLock(&__CFUniCharPropTableLock);
1204
1205 if (NULL == __CFUniCharUnicodePropertyTable) {
1206 __CFUniCharBitmapData *table;
1207 const void *bytes;
1208 const void *bodyBase;
1209 const void *planeBase;
1210 int headerSize;
1211 int idx, count;
1212 int planeIndex, planeCount;
1213 int planeSize;
1214 int64_t fileSize;
1215
1216 if (!__CFUniCharLoadFile(PROP_DB_FILE, &bytes, &fileSize) || !__CFSimpleFileSizeVerification(bytes, fileSize)) {
1217 __CFUnlock(&__CFUniCharPropTableLock);
1218 return NULL;
1219 }
1220
1221 #if defined (__cplusplus)
1222 bytes = (uint8_t*)bytes + 4; // Skip Unicode version
1223 headerSize = CFSwapInt32BigToHost(*((uint32_t *)bytes)); bytes = (uint8_t *)bytes + sizeof(uint32_t);
1224 #else
1225 bytes += 4; // Skip Unicode version
1226 headerSize = CFSwapInt32BigToHost(*((uint32_t *)bytes)); bytes += sizeof(uint32_t);
1227 #endif
1228
1229 headerSize -= (sizeof(uint32_t) * 2);
1230 bodyBase = (char *)bytes + headerSize;
1231
1232 count = headerSize / sizeof(uint32_t);
1233 __CFUniCharUnicodePropertyTableCount = count;
1234
1235 table = (__CFUniCharBitmapData *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__CFUniCharBitmapData) * count, 0);
1236
1237 for (idx = 0;idx < count;idx++) {
1238 planeCount = *((const uint8_t *)bodyBase);
1239 planeBase = (char *)bodyBase + planeCount + (planeCount % 4 ? 4 - (planeCount % 4) : 0);
1240 table[idx]._planes = (const uint8_t **)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(const void *) * planeCount, 0);
1241
1242 for (planeIndex = 0;planeIndex < planeCount;planeIndex++) {
1243 if ((planeSize = ((const uint8_t *)bodyBase)[planeIndex + 1])) {
1244 table[idx]._planes[planeIndex] = (const uint8_t *)planeBase;
1245 #if defined (__cplusplus)
1246 planeBase = (char*)planeBase + (planeSize * 256);
1247 #else
1248 planeBase += (planeSize * 256);
1249 #endif
1250 } else {
1251 table[idx]._planes[planeIndex] = NULL;
1252 }
1253 }
1254
1255 table[idx]._numPlanes = planeCount;
1256 #if defined (__cplusplus)
1257 bodyBase = (const uint8_t *)bodyBase + (CFSwapInt32BigToHost(*(uint32_t *)bytes));
1258 ((uint32_t *&)bytes) ++;
1259 #else
1260 bodyBase += (CFSwapInt32BigToHost(*((uint32_t *)bytes++)));
1261 #endif
1262 }
1263
1264 __CFUniCharUnicodePropertyTable = table;
1265 }
1266
1267 __CFUnlock(&__CFUniCharPropTableLock);
1268
1269 return (plane < __CFUniCharUnicodePropertyTable[propertyType]._numPlanes ? __CFUniCharUnicodePropertyTable[propertyType]._planes[plane] : NULL);
1270 }
1271
1272 CF_PRIVATE uint32_t CFUniCharGetNumberOfPlanesForUnicodePropertyData(uint32_t propertyType) {
1273 (void)CFUniCharGetUnicodePropertyDataForPlane(propertyType, 0);
1274 return __CFUniCharUnicodePropertyTable[propertyType]._numPlanes;
1275 }
1276
1277 CF_PRIVATE uint32_t CFUniCharGetUnicodeProperty(UTF32Char character, uint32_t propertyType) {
1278 if (propertyType == kCFUniCharCombiningProperty) {
1279 return CFUniCharGetCombiningPropertyForCharacter(character, (const uint8_t *)CFUniCharGetUnicodePropertyDataForPlane(propertyType, (character >> 16) & 0xFF));
1280 } else if (propertyType == kCFUniCharBidiProperty) {
1281 return CFUniCharGetBidiPropertyForCharacter(character, (const uint8_t *)CFUniCharGetUnicodePropertyDataForPlane(propertyType, (character >> 16) & 0xFF));
1282 } else {
1283 return 0;
1284 }
1285 }
1286
1287
1288
1289 /*
1290 The UTF8 conversion in the following function is derived from ConvertUTF.c
1291 */
1292 /*
1293 * Copyright 2001 Unicode, Inc.
1294 *
1295 * Disclaimer
1296 *
1297 * This source code is provided as is by Unicode, Inc. No claims are
1298 * made as to fitness for any particular purpose. No warranties of any
1299 * kind are expressed or implied. The recipient agrees to determine
1300 * applicability of information provided. If this file has been
1301 * purchased on magnetic or optical media from Unicode, Inc., the
1302 * sole remedy for any claim will be exchange of defective media
1303 * within 90 days of receipt.
1304 *
1305 * Limitations on Rights to Redistribute This Code
1306 *
1307 * Unicode, Inc. hereby grants the right to freely use the information
1308 * supplied in this file in the creation of products supporting the
1309 * Unicode Standard, and to make copies of this file in any form
1310 * for internal or external distribution as long as this notice
1311 * remains attached.
1312 */
1313 #define UNI_REPLACEMENT_CHAR (0x0000FFFDUL)
1314
1315 bool CFUniCharFillDestinationBuffer(const UTF32Char *src, CFIndex srcLength, void **dst, CFIndex dstLength, CFIndex *filledLength, uint32_t dstFormat) {
1316 UTF32Char currentChar;
1317 CFIndex usedLength = *filledLength;
1318
1319 if (dstFormat == kCFUniCharUTF16Format) {
1320 UTF16Char *dstBuffer = (UTF16Char *)*dst;
1321
1322 while (srcLength-- > 0) {
1323 currentChar = *(src++);
1324
1325 if (currentChar > 0xFFFF) { // Non-BMP
1326 usedLength += 2;
1327 if (dstLength) {
1328 if (usedLength > dstLength) return false;
1329 currentChar -= 0x10000;
1330 *(dstBuffer++) = (UTF16Char)((currentChar >> 10) + 0xD800UL);
1331 *(dstBuffer++) = (UTF16Char)((currentChar & 0x3FF) + 0xDC00UL);
1332 }
1333 } else {
1334 ++usedLength;
1335 if (dstLength) {
1336 if (usedLength > dstLength) return false;
1337 *(dstBuffer++) = (UTF16Char)currentChar;
1338 }
1339 }
1340 }
1341
1342 *dst = dstBuffer;
1343 } else if (dstFormat == kCFUniCharUTF8Format) {
1344 uint8_t *dstBuffer = (uint8_t *)*dst;
1345 uint16_t bytesToWrite = 0;
1346 const UTF32Char byteMask = 0xBF;
1347 const UTF32Char byteMark = 0x80;
1348 static const uint8_t firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
1349
1350 while (srcLength-- > 0) {
1351 currentChar = *(src++);
1352
1353 /* Figure out how many bytes the result will require */
1354 if (currentChar < (UTF32Char)0x80) {
1355 bytesToWrite = 1;
1356 } else if (currentChar < (UTF32Char)0x800) {
1357 bytesToWrite = 2;
1358 } else if (currentChar < (UTF32Char)0x10000) {
1359 bytesToWrite = 3;
1360 } else if (currentChar < (UTF32Char)0x200000) {
1361 bytesToWrite = 4;
1362 } else {
1363 bytesToWrite = 2;
1364 currentChar = UNI_REPLACEMENT_CHAR;
1365 }
1366
1367 usedLength += bytesToWrite;
1368
1369 if (dstLength) {
1370 if (usedLength > dstLength) return false;
1371
1372 dstBuffer += bytesToWrite;
1373 switch (bytesToWrite) { /* note: everything falls through. */
1374 case 4: *--dstBuffer = (currentChar | byteMark) & byteMask; currentChar >>= 6;
1375 case 3: *--dstBuffer = (currentChar | byteMark) & byteMask; currentChar >>= 6;
1376 case 2: *--dstBuffer = (currentChar | byteMark) & byteMask; currentChar >>= 6;
1377 case 1: *--dstBuffer = currentChar | firstByteMark[bytesToWrite];
1378 }
1379 dstBuffer += bytesToWrite;
1380 }
1381 }
1382
1383 *dst = dstBuffer;
1384 } else {
1385 UTF32Char *dstBuffer = (UTF32Char *)*dst;
1386
1387 while (srcLength-- > 0) {
1388 currentChar = *(src++);
1389
1390 ++usedLength;
1391 if (dstLength) {
1392 if (usedLength > dstLength) return false;
1393 *(dstBuffer++) = currentChar;
1394 }
1395 }
1396
1397 *dst = dstBuffer;
1398 }
1399
1400 *filledLength = usedLength;
1401
1402 return true;
1403 }
1404
1405 #if DEPLOYMENT_TARGET_WINDOWS
1406 void __CFUniCharCleanup(void)
1407 {
1408 int idx;
1409
1410 // cleanup memory allocated by __CFUniCharLoadBitmapData()
1411 __CFLock(&__CFUniCharBitmapLock);
1412
1413 if (__CFUniCharBitmapDataArray != NULL) {
1414 for (idx = 0; idx < (int)__CFUniCharNumberOfBitmaps; idx++) {
1415 CFAllocatorDeallocate(kCFAllocatorSystemDefault, __CFUniCharBitmapDataArray[idx]._planes);
1416 __CFUniCharBitmapDataArray[idx]._planes = NULL;
1417 }
1418
1419 CFAllocatorDeallocate(kCFAllocatorSystemDefault, __CFUniCharBitmapDataArray);
1420 __CFUniCharBitmapDataArray = NULL;
1421 __CFUniCharNumberOfBitmaps = 0;
1422 }
1423
1424 __CFUnlock(&__CFUniCharBitmapLock);
1425
1426 // cleanup memory allocated by CFUniCharGetMappingData()
1427 __CFLock(&__CFUniCharMappingTableLock);
1428
1429 if (__CFUniCharMappingTables != NULL) {
1430 CFAllocatorDeallocate(kCFAllocatorSystemDefault, __CFUniCharMappingTables);
1431 __CFUniCharMappingTables = NULL;
1432 }
1433
1434 // cleanup memory allocated by __CFUniCharLoadCaseMappingTable()
1435 if (__CFUniCharCaseMappingTableCounts != NULL) {
1436 CFAllocatorDeallocate(kCFAllocatorSystemDefault, __CFUniCharCaseMappingTableCounts);
1437 __CFUniCharCaseMappingTableCounts = NULL;
1438
1439 __CFUniCharCaseMappingTable = NULL;
1440 __CFUniCharCaseMappingExtraTable = NULL;
1441 }
1442
1443 __CFUnlock(&__CFUniCharMappingTableLock);
1444
1445 // cleanup memory allocated by CFUniCharGetUnicodePropertyDataForPlane()
1446 __CFLock(&__CFUniCharPropTableLock);
1447
1448 if (__CFUniCharUnicodePropertyTable != NULL) {
1449 for (idx = 0; idx < __CFUniCharUnicodePropertyTableCount; idx++) {
1450 CFAllocatorDeallocate(kCFAllocatorSystemDefault, __CFUniCharUnicodePropertyTable[idx]._planes);
1451 __CFUniCharUnicodePropertyTable[idx]._planes = NULL;
1452 }
1453
1454 CFAllocatorDeallocate(kCFAllocatorSystemDefault, __CFUniCharUnicodePropertyTable);
1455 __CFUniCharUnicodePropertyTable = NULL;
1456 __CFUniCharUnicodePropertyTableCount = 0;
1457 }
1458
1459 __CFUnlock(&__CFUniCharPropTableLock);
1460 }
1461 #endif
1462
1463 #undef USE_MACHO_SEGMENT
1464