#include <CoreFoundation/CFByteOrder.h>
#include "CFInternal.h"
#include "CFUniChar.h"
#include "CFStringEncodingConverterExt.h"
#include "CFUnicodeDecomposition.h"
#include "CFUniCharPriv.h"
#if defined(__MACOS8__)
#include <stdio.h>
#elif defined(__WIN32__)
#include <windows.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <io.h>
#elif defined(__MACH__) || defined(__LINUX__) || defined(__FREEBSD__)
#if defined(__MACH__)
#include <mach/mach.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#endif
#if defined(__MACOS8__)
#define MAXPATHLEN FILENAME_MAX
#elif defined WIN32
#define MAXPATHLEN MAX_PATH
#endif
#if !defined(__MACOS8__)
CF_INLINE void __CFUniCharCharacterSetPath(char *cpath) {
#if defined(__MACH__)
strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
#elif defined(__WIN32__)
strlcpy(cpath, _CFDLLPath(), MAXPATHLEN);
#else
strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
#endif
#if defined(__WIN32__)
strlcat(cpath, "\\CharacterSets\\", MAXPATHLEN);
#else
strlcat(cpath, "/CharacterSets/", MAXPATHLEN);
#endif
}
static bool __CFUniCharLoadBytesFromFile(const char *fileName, const void **bytes) {
#if defined(__WIN32__)
HANDLE bitmapFileHandle;
HANDLE mappingHandle;
if ((bitmapFileHandle = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) return false;
mappingHandle = CreateFileMapping(bitmapFileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
CloseHandle(bitmapFileHandle);
if (!mappingHandle) return false;
*bytes = MapViewOfFileEx(mappingHandle, FILE_MAP_READ, 0, 0, 0, NULL);
CloseHandle(mappingHandle);
return (*bytes ? true : false);
#else
struct stat statBuf;
int fd = -1;
if ((fd = open(fileName, O_RDONLY, 0)) < 0) return false;
if (fstat(fd, &statBuf) < 0 || (*bytes = mmap(0, statBuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1) {
close(fd);
return false;
}
close(fd);
return true;
#endif
}
static bool __CFUniCharLoadFile(const char *bitmapName, const void **bytes) {
char cpath[MAXPATHLEN];
__CFUniCharCharacterSetPath(cpath);
strlcat(cpath, bitmapName, MAXPATHLEN);
return __CFUniCharLoadBytesFromFile(cpath, bytes);
}
#endif !defined(__MACOS8__)
CF_INLINE bool isControl(UTF32Char theChar, uint16_t charset, const void *data) { if ((theChar <= 0x001F) || (theChar >= 0x007F && theChar <= 0x009F)) return true;
return false;
}
CF_INLINE bool isWhitespace(UTF32Char theChar, uint16_t charset, const void *data) { if ((theChar == 0x0020) || (theChar == 0x0009) || (theChar == 0x00A0) || (theChar == 0x1680) || (theChar >= 0x2000 && theChar <= 0x200B) || (theChar == 0x202F) || (theChar == 0x205F) || (theChar == 0x3000)) return true;
return false;
}
CF_INLINE bool isWhitespaceAndNewLine(UTF32Char theChar, uint16_t charset, const void *data) { if (isWhitespace(theChar, charset, data) || (theChar >= 0x000A && theChar <= 0x000D) || (theChar == 0x0085) || (theChar == 0x2028) || (theChar == 0x2029)) return true;
return false;
}
#if defined(__MACOS8__)
typedef struct _CFCharSetPrivateStruct {
int issorted;
int bitrange[4];
int nsingles;
int nranges;
int singmin;
int singmax;
int array[1];
} CFCharSetPrivateStruct;
CF_INLINE bool __CFCSetIsMemberSet(const CFCharSetPrivateStruct *set, UTF16Char theChar) {
int *tmp, *tmp2;
int i, nel;
int *p, *q, *wari;
if (set->issorted != 1) {
return false;
}
theChar &= 0x0001FFFF;
if (__CFCSetBitsInRange(theChar, set->bitrange)) {
if (theChar >= set->singmin && theChar <= set->singmax) {
tmp = (int *) &(set->array[0]);
if ((nel = set->nsingles) < __kCFSetBreakeven) {
for (i = 0; i < nel; i++) {
if (*tmp == theChar) return true;
++tmp;
}
}
else { p = tmp; q = tmp + (nel-1);
while (p <= q) {
wari = (p + ((q-p)>>1));
if (theChar < *wari) q = wari - 1;
else if (theChar > *wari) p = wari + 1;
else return true;
}
}
}
tmp = (int *) &(set->array[0]) + set->nsingles;
if ((nel = set->nranges) < __kCFSetBreakeven) {
i = nel;
tmp2 = tmp+1;
while (i) {
if (theChar <= *tmp2) {
if (theChar >= *tmp) return true;
}
tmp += 2;
tmp2 = tmp+1;
--i;
}
} else {
p = tmp; q = tmp + (2*nel-2);
while (p <= q) {
i = (q - p) >> 1;
wari = p + (i & 0xFFFFFFFE);
if (theChar < *wari) q = wari - 2;
else if (theChar > *(wari + 1)) p = wari + 2;
else return true;
}
}
return false;
}
return false;
}
CF_INLINE void __CFCSetBitmapProcessManyCharacters(unsigned char *map, unsigned n, unsigned m) {
unsigned tmp;
for (tmp = n; tmp <= m; tmp++) CFUniCharAddCharacterToBitmap(tmp, map);
}
CF_INLINE void __CFCSetMakeSetBitmapFromSet(const CFCharSetPrivateStruct *theSet, uint8_t *map)
{
int *ip;
UTF16Char ctmp;
int cnt;
for (cnt = 0; cnt < theSet->nsingles; cnt++) {
ctmp = theSet->array[cnt];
CFUniCharAddCharacterToBitmap(tmp, map);
}
ip = (int *) (&(theSet->array[0]) + theSet->nsingles);
cnt = theSet->nranges;
while (cnt) {
__CFCSetBitmapProcessManyCharacters((unsigned char *)map, *ip, *(ip+1));
ip += 2;
--cnt;
}
}
extern const CFCharSetPrivateStruct *_CFdecimalDigitCharacterSetData;
extern const CFCharSetPrivateStruct *_CFletterCharacterSetData;
extern const CFCharSetPrivateStruct *_CFlowercaseLetterCharacterSetData;
extern const CFCharSetPrivateStruct *_CFuppercaseLetterCharacterSetData;
extern const CFCharSetPrivateStruct *_CFnonBaseCharacterSetData;
extern const CFCharSetPrivateStruct *_CFdecomposableCharacterSetData;
extern const CFCharSetPrivateStruct *_CFpunctuationCharacterSetData;
extern const CFCharSetPrivateStruct *_CFalphanumericCharacterSetData;
extern const CFCharSetPrivateStruct *_CFillegalCharacterSetData;
extern const CFCharSetPrivateStruct *_CFhasNonSelfLowercaseMappingData;
extern const CFCharSetPrivateStruct *_CFhasNonSelfUppercaseMappingData;
extern const CFCharSetPrivateStruct *_CFhasNonSelfTitlecaseMappingData;
#else __MACOS8__
typedef struct {
uint32_t _numPlanes;
const uint8_t **_planes;
} __CFUniCharBitmapData;
static char __CFUniCharUnicodeVersionString[8] = {0, 0, 0, 0, 0, 0, 0, 0};
static uint32_t __CFUniCharNumberOfBitmaps = 0;
static __CFUniCharBitmapData *__CFUniCharBitmapDataArray = NULL;
static CFSpinLock_t __CFUniCharBitmapLock = 0;
#ifndef CF_UNICHAR_BITMAP_FILE
#define CF_UNICHAR_BITMAP_FILE "CFCharacterSetBitmaps.bitmap"
#endif CF_UNICHAR_BITMAP_FILE
static bool __CFUniCharLoadBitmapData(void) {
uint32_t headerSize;
uint32_t bitmapSize;
int numPlanes;
uint8_t currentPlane;
const void *bytes;
const void *bitmapBase;
const void *bitmap;
int idx, bitmapIndex;
__CFSpinLock(&__CFUniCharBitmapLock);
if (__CFUniCharBitmapDataArray || !__CFUniCharLoadFile(CF_UNICHAR_BITMAP_FILE, &bytes)) {
__CFSpinUnlock(&__CFUniCharBitmapLock);
return false;
}
for (idx = 0;idx < 4 && ((const uint8_t *)bytes)[idx];idx++) {
__CFUniCharUnicodeVersionString[idx * 2] = ((const uint8_t *)bytes)[idx];
__CFUniCharUnicodeVersionString[idx * 2 + 1] = '.';
}
__CFUniCharUnicodeVersionString[(idx < 4 ? idx * 2 - 1 : 7)] = '\0';
headerSize = CFSwapInt32BigToHost(*((uint32_t *)((char *)bytes + 4)));
bitmapBase = (char *)bytes + headerSize;
(char *)bytes += (sizeof(uint32_t) * 2);
headerSize -= (sizeof(uint32_t) * 2);
__CFUniCharNumberOfBitmaps = headerSize / (sizeof(uint32_t) * 2);
__CFUniCharBitmapDataArray = (__CFUniCharBitmapData *)CFAllocatorAllocate(NULL, sizeof(__CFUniCharBitmapData) * __CFUniCharNumberOfBitmaps, 0);
for (idx = 0;idx < (int)__CFUniCharNumberOfBitmaps;idx++) {
bitmap = (char *)bitmapBase + CFSwapInt32BigToHost(*(((uint32_t *)bytes)++));
bitmapSize = CFSwapInt32BigToHost(*(((uint32_t *)bytes)++));
numPlanes = bitmapSize / (8 * 1024);
numPlanes = *(const uint8_t *)((char *)bitmap + (((numPlanes - 1) * ((8 * 1024) + 1)) - 1)) + 1;
__CFUniCharBitmapDataArray[idx]._planes = (const uint8_t **)CFAllocatorAllocate(NULL, sizeof(const void *) * numPlanes, 0);
__CFUniCharBitmapDataArray[idx]._numPlanes = numPlanes;
currentPlane = 0;
for (bitmapIndex = 0;bitmapIndex < numPlanes;bitmapIndex++) {
if (bitmapIndex == currentPlane) {
__CFUniCharBitmapDataArray[idx]._planes[bitmapIndex] = bitmap;
(char *)bitmap += (8 * 1024);
currentPlane = *(((const uint8_t *)bitmap)++);
} else {
__CFUniCharBitmapDataArray[idx]._planes[bitmapIndex] = NULL;
}
}
}
__CFSpinUnlock(&__CFUniCharBitmapLock);
return true;
}
__private_extern__ const char *__CFUniCharGetUnicodeVersionString(void) {
if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
return __CFUniCharUnicodeVersionString;
}
#endif __MACOS8__
#define CONTROLSET_HAS_FORMATTER 1
bool CFUniCharIsMemberOf(UTF32Char theChar, uint32_t charset) {
#if CONTROLSET_HAS_FORMATTER
if (charset == kCFUniCharControlCharacterSet) charset = kCFUniCharControlAndFormatterCharacterSet;
#endif CONTROLSET_HAS_FORMATTER
switch (charset) {
case kCFUniCharControlCharacterSet:
return isControl(theChar, charset, NULL);
case kCFUniCharWhitespaceCharacterSet:
return isWhitespace(theChar, charset, NULL);
case kCFUniCharWhitespaceAndNewlineCharacterSet:
return isWhitespaceAndNewLine(theChar, charset, NULL);
#if defined(__MACOS8__)
case kCFUniCharDecimalDigitCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFdecimalDigitCharacterSetData, theChar);
case kCFUniCharLetterCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFletterCharacterSetData, theChar);
case kCFUniCharLowercaseLetterCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFlowercaseLetterCharacterSetData, theChar);
case kCFUniCharUppercaseLetterCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFuppercaseLetterCharacterSetData, theChar);
case kCFUniCharNonBaseCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFnonBaseCharacterSetData, theChar);
case kCFUniCharAlphaNumericCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFalphanumericCharacterSetData, theChar);
case kCFUniCharDecomposableCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFdecomposableCharacterSetData, theChar);
case kCFUniCharPunctuationCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFpunctuationCharacterSetData, theChar);
case kCFUniCharIllegalCharacterSet:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFillegalCharacterSetData, theChar);
case kCFUniCharHasNonSelfLowercaseMapping:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFhasNonSelfLowercaseMappingData, theChar);
case kCFUniCharHasNonSelfUppercaseMapping:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFhasNonSelfUppercaseMappingData, theChar);
case kCFUniCharHasNonSelfTitlecaseMapping:
return __CFCSetIsMemberSet((const CFCharSetPrivateStruct *)&_CFhasNonSelfTitlecaseMappingData, theChar);
default:
return false;
#else
default:
if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
if ((charset - kCFUniCharDecimalDigitCharacterSet) < __CFUniCharNumberOfBitmaps) {
__CFUniCharBitmapData *data = __CFUniCharBitmapDataArray + (charset - kCFUniCharDecimalDigitCharacterSet);
uint8_t planeNo = (theChar >> 16) & 0xFF;
if (charset == kCFUniCharIllegalCharacterSet) {
if (planeNo == 0x0E) { theChar &= 0xFF;
return (((theChar == 0x01) || ((theChar > 0x1F) && (theChar < 0x80))) ? false : true);
} else if (planeNo == 0x0F || planeNo == 0x10) { return ((theChar & 0xFF) > 0xFFFD ? true : false);
} else {
return (planeNo < data->_numPlanes && data->_planes[planeNo] ? !CFUniCharIsMemberOfBitmap(theChar, data->_planes[planeNo]) : true);
}
} else if (charset == kCFUniCharControlAndFormatterCharacterSet) {
if (planeNo == 0x0E) { theChar &= 0xFF;
return (((theChar == 0x01) || ((theChar > 0x1F) && (theChar < 0x80))) ? true : false);
} else {
return (planeNo < data->_numPlanes && data->_planes[planeNo] ? CFUniCharIsMemberOfBitmap(theChar, data->_planes[planeNo]) : false);
}
} else {
return (planeNo < data->_numPlanes && data->_planes[planeNo] ? CFUniCharIsMemberOfBitmap(theChar, data->_planes[planeNo]) : false);
}
}
return false;
#endif
}
}
const uint8_t *CFUniCharGetBitmapPtrForPlane(uint32_t charset, uint32_t plane) {
if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
#if CONTROLSET_HAS_FORMATTER
if (charset == kCFUniCharControlCharacterSet) charset = kCFUniCharControlAndFormatterCharacterSet;
#endif CONTROLSET_HAS_FORMATTER
if (charset > kCFUniCharWhitespaceAndNewlineCharacterSet && (charset - kCFUniCharDecimalDigitCharacterSet) < __CFUniCharNumberOfBitmaps && charset != kCFUniCharIllegalCharacterSet) {
__CFUniCharBitmapData *data = __CFUniCharBitmapDataArray + (charset - kCFUniCharDecimalDigitCharacterSet);
return (plane < data->_numPlanes ? data->_planes[plane] : NULL);
}
return NULL;
}
__private_extern__ uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t plane, void *bitmap, bool isInverted) {
const uint8_t *src = CFUniCharGetBitmapPtrForPlane(charset, plane);
int numBytes = (8 * 1024);
if (src) {
if (isInverted) {
while (numBytes-- > 0) *(((uint8_t *)bitmap)++) = ~(*(src++));
} else {
while (numBytes-- > 0) *(((uint8_t *)bitmap)++) = *(src++);
}
return kCFUniCharBitmapFilled;
} else if (charset == kCFUniCharIllegalCharacterSet) {
__CFUniCharBitmapData *data = __CFUniCharBitmapDataArray + (charset - kCFUniCharDecimalDigitCharacterSet);
if (plane < data->_numPlanes && (src = data->_planes[plane])) {
if (isInverted) {
while (numBytes-- > 0) *(((uint8_t *)bitmap)++) = *(src++);
} else {
while (numBytes-- > 0) *(((uint8_t *)bitmap)++) = ~(*(src++));
}
return kCFUniCharBitmapFilled;
} else if (plane == 0x0E) { int idx;
uint8_t asciiRange = (isInverted ? (uint8_t)0xFF : (uint8_t)0);
uint8_t otherRange = (isInverted ? (uint8_t)0 : (uint8_t)0xFF);
*(((uint8_t *)bitmap)++) = 0x02; for (idx = 1;idx < numBytes;idx++) {
*(((uint8_t *)bitmap)++) = ((idx >= (0x20 / 8) && (idx < (0x80 / 8))) ? asciiRange : otherRange);
}
return kCFUniCharBitmapFilled;
} else if (plane == 0x0F || plane == 0x10) { uint32_t value = (isInverted ? 0xFFFFFFFF : 0);
numBytes /= 4;
while (numBytes-- > 0) *(((uint32_t *)bitmap)++) = value;
*(((uint8_t *)bitmap) - 5) = (isInverted ? 0x3F : 0xC0); return kCFUniCharBitmapFilled;
}
return (isInverted ? kCFUniCharBitmapEmpty : kCFUniCharBitmapAll);
#if CONTROLSET_HAS_FORMATTER
} else if ((charset == kCFUniCharControlCharacterSet) && (plane == 0x0E)) { int idx;
uint8_t asciiRange = (isInverted ? (uint8_t)0 : (uint8_t)0xFF);
uint8_t otherRange = (isInverted ? (uint8_t)0xFF : (uint8_t)0);
*(((uint8_t *)bitmap)++) = 0x02; for (idx = 1;idx < numBytes;idx++) {
*(((uint8_t *)bitmap)++) = ((idx >= (0x20 / 8) && (idx < (0x80 / 8))) ? asciiRange : otherRange);
}
return kCFUniCharBitmapFilled;
#endif CONTROLSET_HAS_FORMATTER
} else if (charset < kCFUniCharDecimalDigitCharacterSet) {
if (plane) return (isInverted ? kCFUniCharBitmapAll : kCFUniCharBitmapEmpty);
if (charset == kCFUniCharControlCharacterSet) {
int idx;
uint8_t nonFillValue = (isInverted ? (uint8_t)0xFF : (uint8_t)0);
uint8_t fillValue = (isInverted ? (uint8_t)0 : (uint8_t)0xFF);
uint8_t *bitmapP = (uint8_t *)bitmap;
for (idx = 0;idx < numBytes;idx++) {
*(bitmapP++) = (idx < (0x20 / 8) || (idx >= (0x80 / 8) && idx < (0xA0 / 8)) ? fillValue : nonFillValue);
}
if (isInverted) {
CFUniCharRemoveCharacterFromBitmap(0x007F, bitmap);
} else {
CFUniCharAddCharacterToBitmap(0x007F, bitmap);
}
} else {
uint8_t *bitmapBase = (uint8_t *)bitmap;
int idx;
uint8_t nonFillValue = (isInverted ? (uint8_t)0xFF : (uint8_t)0);
while (numBytes-- > 0) *(((uint8_t *)bitmap)++) = nonFillValue;
if (charset == kCFUniCharWhitespaceAndNewlineCharacterSet) {
static const UniChar newlines[] = {0x000A, 0x000B, 0x000C, 0x000D, 0x0085, 0x2028, 0x2029};
for (idx = 0;idx < (int)(sizeof(newlines) / sizeof(*newlines)); idx++) {
if (isInverted) {
CFUniCharRemoveCharacterFromBitmap(newlines[idx], bitmapBase);
} else {
CFUniCharAddCharacterToBitmap(newlines[idx], bitmapBase);
}
}
}
if (isInverted) {
CFUniCharRemoveCharacterFromBitmap(0x0009, bitmapBase);
CFUniCharRemoveCharacterFromBitmap(0x0020, bitmapBase);
CFUniCharRemoveCharacterFromBitmap(0x00A0, bitmapBase);
CFUniCharRemoveCharacterFromBitmap(0x1680, bitmapBase);
CFUniCharRemoveCharacterFromBitmap(0x202F, bitmapBase);
CFUniCharRemoveCharacterFromBitmap(0x205F, bitmapBase);
CFUniCharRemoveCharacterFromBitmap(0x3000, bitmapBase);
} else {
CFUniCharAddCharacterToBitmap(0x0009, bitmapBase);
CFUniCharAddCharacterToBitmap(0x0020, bitmapBase);
CFUniCharAddCharacterToBitmap(0x00A0, bitmapBase);
CFUniCharAddCharacterToBitmap(0x1680, bitmapBase);
CFUniCharAddCharacterToBitmap(0x202F, bitmapBase);
CFUniCharAddCharacterToBitmap(0x205F, bitmapBase);
CFUniCharAddCharacterToBitmap(0x3000, bitmapBase);
}
for (idx = 0x2000;idx <= 0x200B;idx++) {
if (isInverted) {
CFUniCharRemoveCharacterFromBitmap(idx, bitmapBase);
} else {
CFUniCharAddCharacterToBitmap(idx, bitmapBase);
}
}
}
return kCFUniCharBitmapFilled;
}
return (isInverted ? kCFUniCharBitmapAll : kCFUniCharBitmapEmpty);
}
__private_extern__ uint32_t CFUniCharGetNumberOfPlanes(uint32_t charset) {
#if defined(__MACOS8__)
return 1;
#else __MACOS8__
#if CONTROLSET_HAS_FORMATTER
if (charset == kCFUniCharControlCharacterSet) return 15; #endif CONTROLSET_HAS_FORMATTER
if (charset < kCFUniCharDecimalDigitCharacterSet) {
return 1;
} else if (charset == kCFUniCharIllegalCharacterSet) {
return 17;
} else {
uint32_t numPlanes;
if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
numPlanes = __CFUniCharBitmapDataArray[charset - kCFUniCharDecimalDigitCharacterSet]._numPlanes;
return numPlanes;
}
#endif __MACOS8__
}
static const void **__CFUniCharMappingTables = NULL;
static CFSpinLock_t __CFUniCharMappingTableLock = 0;
#if defined(__BIG_ENDIAN__)
#define MAPPING_TABLE_FILE "CFUnicodeData-B.mapping"
#else __BIG_ENDIAN__
#define MAPPING_TABLE_FILE "CFUnicodeData-L.mapping"
#endif __BIG_ENDIAN__
__private_extern__ const void *CFUniCharGetMappingData(uint32_t type) {
__CFSpinLock(&__CFUniCharMappingTableLock);
if (NULL == __CFUniCharMappingTables) {
const void *bytes;
const void *bodyBase;
int headerSize;
int idx, count;
if (!__CFUniCharLoadFile(MAPPING_TABLE_FILE, &bytes)) {
__CFSpinUnlock(&__CFUniCharMappingTableLock);
return NULL;
}
(char *)bytes += 4; headerSize = *(((uint32_t *)bytes)++);
headerSize -= (sizeof(uint32_t) * 2);
bodyBase = (char *)bytes + headerSize;
count = headerSize / sizeof(uint32_t);
__CFUniCharMappingTables = (const void **)CFAllocatorAllocate(NULL, sizeof(const void *) * count, 0);
for (idx = 0;idx < count;idx++) {
__CFUniCharMappingTables[idx] = (char *)bodyBase + *(((uint32_t *)bytes)++);
}
}
__CFSpinUnlock(&__CFUniCharMappingTableLock);
return __CFUniCharMappingTables[type];
}
#define DO_SPECIAL_CASE_MAPPING 1
static uint32_t *__CFUniCharCaseMappingTableCounts = NULL;
static uint32_t **__CFUniCharCaseMappingTable = NULL;
static const uint32_t **__CFUniCharCaseMappingExtraTable = NULL;
typedef struct {
uint32_t _key;
uint32_t _value;
} __CFUniCharCaseMappings;
static uint32_t __CFUniCharGetMappedCase(const __CFUniCharCaseMappings *theTable, uint32_t numElem, UTF32Char character) {
const __CFUniCharCaseMappings *p, *q, *divider;
if ((character < theTable[0]._key) || (character > theTable[numElem-1]._key)) {
return 0;
}
p = theTable;
q = p + (numElem-1);
while (p <= q) {
divider = p + ((q - p) >> 1);
if (character < divider->_key) { q = divider - 1; }
else if (character > divider->_key) { p = divider + 1; }
else { return divider->_value; }
}
return 0;
}
#define NUM_CASE_MAP_DATA (kCFUniCharCaseFold + 1)
static bool __CFUniCharLoadCaseMappingTable(void) {
int idx;
if (NULL == __CFUniCharMappingTables) (void)CFUniCharGetMappingData(kCFUniCharToLowercase);
if (NULL == __CFUniCharMappingTables) return false;
__CFSpinLock(&__CFUniCharMappingTableLock);
if (__CFUniCharCaseMappingTableCounts) {
__CFSpinUnlock(&__CFUniCharMappingTableLock);
return true;
}
__CFUniCharCaseMappingTableCounts = (uint32_t *)CFAllocatorAllocate(NULL, sizeof(uint32_t) * NUM_CASE_MAP_DATA + sizeof(uint32_t *) * NUM_CASE_MAP_DATA * 2, 0);
__CFUniCharCaseMappingTable = (uint32_t **)((char *)__CFUniCharCaseMappingTableCounts + sizeof(uint32_t) * NUM_CASE_MAP_DATA);
__CFUniCharCaseMappingExtraTable = (const uint32_t **)__CFUniCharCaseMappingTable + NUM_CASE_MAP_DATA;
for (idx = 0;idx < NUM_CASE_MAP_DATA;idx++) {
__CFUniCharCaseMappingTableCounts[idx] = *((uint32_t *)__CFUniCharMappingTables[idx]) / (sizeof(uint32_t) * 2);
__CFUniCharCaseMappingTable[idx] = ((uint32_t *)__CFUniCharMappingTables[idx]) + 1;
__CFUniCharCaseMappingExtraTable[idx] = (const uint32_t *)((char *)__CFUniCharCaseMappingTable[idx] + *((uint32_t *)__CFUniCharMappingTables[idx]));
}
__CFSpinUnlock(&__CFUniCharMappingTableLock);
return true;
}
#if __BIG_ENDIAN__
#define TURKISH_LANG_CODE (0x7472) // tr
#define LITHUANIAN_LANG_CODE (0x6C74) // lt
#define AZERI_LANG_CODE (0x617A) // az
#else __BIG_ENDIAN__
#define TURKISH_LANG_CODE (0x7274) // tr
#define LITHUANIAN_LANG_CODE (0x746C) // lt
#define AZERI_LANG_CODE (0x7A61) // az
#endif __BIG_ENDIAN__
uint32_t CFUniCharMapCaseTo(UTF32Char theChar, UTF16Char *convertedChar, uint32_t maxLength, uint32_t ctype, uint32_t flags, const uint8_t *langCode) {
__CFUniCharBitmapData *data;
uint8_t planeNo = (theChar >> 16) & 0xFF;
caseFoldRetry:
#if DO_SPECIAL_CASE_MAPPING
if (flags & kCFUniCharCaseMapFinalSigma) {
if (theChar == 0x03A3) { *convertedChar = (ctype == kCFUniCharToLowercase ? 0x03C2 : 0x03A3);
return 1;
}
}
if (langCode) {
switch (*(uint16_t *)langCode) {
case LITHUANIAN_LANG_CODE:
if (theChar == 0x0307 && (flags & kCFUniCharCaseMapAfter_i)) {
return 0;
} else if (ctype == kCFUniCharToLowercase) {
if (flags & kCFUniCharCaseMapMoreAbove) {
switch (theChar) {
case 0x0049: *(convertedChar++) = 0x0069;
*(convertedChar++) = 0x0307;
return 2;
case 0x004A: *(convertedChar++) = 0x006A;
*(convertedChar++) = 0x0307;
return 2;
case 0x012E: *(convertedChar++) = 0x012F;
*(convertedChar++) = 0x0307;
return 2;
default: break;
}
}
switch (theChar) {
case 0x00CC: *(convertedChar++) = 0x0069;
*(convertedChar++) = 0x0307;
*(convertedChar++) = 0x0300;
return 3;
case 0x00CD: *(convertedChar++) = 0x0069;
*(convertedChar++) = 0x0307;
*(convertedChar++) = 0x0301;
return 3;
case 0x0128: *(convertedChar++) = 0x0069;
*(convertedChar++) = 0x0307;
*(convertedChar++) = 0x0303;
return 3;
default: break;
}
}
break;
case TURKISH_LANG_CODE:
case AZERI_LANG_CODE:
if ((theChar == 0x0049) || (theChar == 0x0131)) { *convertedChar = (((ctype == kCFUniCharToLowercase) || (ctype == kCFUniCharCaseFold)) ? ((kCFUniCharCaseMapMoreAbove & flags) ? 0x0069 : 0x0131) : 0x0049);
return 1;
} else if ((theChar == 0x0069) || (theChar == 0x0130)) { *convertedChar = (((ctype == kCFUniCharToLowercase) || (ctype == kCFUniCharCaseFold)) ? 0x0069 : 0x0130);
return 1;
} else if (theChar == 0x0307 && (kCFUniCharCaseMapAfter_i & flags)) { if (ctype == kCFUniCharToLowercase) {
return 0;
} else {
*convertedChar = 0x0307;
return 1;
}
}
break;
default: break;
}
}
#endif DO_SPECIAL_CASE_MAPPING
if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData();
data = __CFUniCharBitmapDataArray + ((ctype + kCFUniCharHasNonSelfLowercaseCharacterSet) - kCFUniCharDecimalDigitCharacterSet);
if (planeNo < data->_numPlanes && data->_planes[planeNo] && CFUniCharIsMemberOfBitmap(theChar, data->_planes[planeNo]) && (__CFUniCharCaseMappingTableCounts || __CFUniCharLoadCaseMappingTable())) {
uint32_t value = __CFUniCharGetMappedCase((const __CFUniCharCaseMappings *)__CFUniCharCaseMappingTable[ctype], __CFUniCharCaseMappingTableCounts[ctype], theChar);
if (!value && ctype == kCFUniCharToTitlecase) {
value = __CFUniCharGetMappedCase((const __CFUniCharCaseMappings *)__CFUniCharCaseMappingTable[kCFUniCharToUppercase], __CFUniCharCaseMappingTableCounts[kCFUniCharToUppercase], theChar);
if (value) ctype = kCFUniCharToUppercase;
}
if (value) {
int count = CFUniCharConvertFlagToCount(value);
if (count == 1) {
if (value & kCFUniCharNonBmpFlag) {
if (maxLength > 1) {
value = (value & 0xFFFFFF) - 0x10000;
*(convertedChar++) = (value >> 10) + 0xD800UL;
*(convertedChar++) = (value & 0x3FF) + 0xDC00UL;
return 2;
}
} else {
*convertedChar = (UTF16Char)value;
return 1;
}
} else if (count < (int)maxLength) {
const uint32_t *extraMapping = __CFUniCharCaseMappingExtraTable[ctype] + (value & 0xFFFFFF);
if (value & kCFUniCharNonBmpFlag) {
int copiedLen = 0;
while (count-- > 0) {
value = *(extraMapping++);
if (value > 0xFFFF) {
if (copiedLen + 2 >= (int)maxLength) break;
value = (value & 0xFFFFFF) - 0x10000;
convertedChar[copiedLen++] = (value >> 10) + 0xD800UL;
convertedChar[copiedLen++] = (value & 0x3FF) + 0xDC00UL;
} else {
if (copiedLen + 1 >= (int)maxLength) break;
convertedChar[copiedLen++] = value;
}
}
if (!count) return copiedLen;
} else {
int idx;
for (idx = 0;idx < count;idx++) *(convertedChar++) = (UTF16Char)*(extraMapping++);
return count;
}
}
}
} else if (ctype == kCFUniCharCaseFold) {
ctype = kCFUniCharToLowercase;
goto caseFoldRetry;
}
if (theChar > 0xFFFF) { theChar = (theChar & 0xFFFFFF) - 0x10000;
*(convertedChar++) = (theChar >> 10) + 0xD800UL;
*(convertedChar++) = (theChar & 0x3FF) + 0xDC00UL;
return 2;
} else {
*convertedChar = theChar;
return 1;
}
}
UInt32 CFUniCharMapTo(UniChar theChar, UniChar *convertedChar, UInt32 maxLength, uint16_t ctype, UInt32 flags) {
if (ctype == kCFUniCharCaseFold + 1) { if (CFUniCharIsDecomposableCharacter(theChar, false)) {
UTF32Char buffer[MAX_DECOMPOSED_LENGTH];
CFIndex usedLength = CFUniCharDecomposeCharacter(theChar, buffer, MAX_DECOMPOSED_LENGTH);
CFIndex idx;
for (idx = 0;idx < usedLength;idx++) *(convertedChar++) = buffer[idx];
return usedLength;
} else {
*convertedChar = theChar;
return 1;
}
} else {
return CFUniCharMapCaseTo(theChar, convertedChar, maxLength, ctype, flags, NULL);
}
}
CF_INLINE bool __CFUniCharIsMoreAbove(UTF16Char *buffer, uint32_t length) {
UTF32Char currentChar;
uint32_t property;
while (length-- > 0) {
currentChar = *(buffer)++;
if (CFUniCharIsSurrogateHighCharacter(currentChar) && (length > 0) && CFUniCharIsSurrogateLowCharacter(*(buffer + 1))) {
currentChar = CFUniCharGetLongCharacterForSurrogatePair(currentChar, *(buffer++));
--length;
}
if (!CFUniCharIsMemberOf(currentChar, kCFUniCharNonBaseCharacterSet)) break;
property = CFUniCharGetCombiningPropertyForCharacter(currentChar, CFUniCharGetUnicodePropertyDataForPlane(kCFUniCharCombiningProperty, (currentChar >> 16) & 0xFF));
if (property == 230) return true; }
return false;
}
CF_INLINE bool __CFUniCharIsAfter_i(UTF16Char *buffer, uint32_t length) {
UTF32Char currentChar = 0;
uint32_t property;
UTF32Char decomposed[MAX_DECOMPOSED_LENGTH];
uint32_t decompLength;
uint32_t idx;
if (length < 1) return 0;
buffer += length;
while (length-- > 1) {
currentChar = *(--buffer);
if (CFUniCharIsSurrogateLowCharacter(currentChar)) {
if ((length > 1) && CFUniCharIsSurrogateHighCharacter(*(buffer - 1))) {
currentChar = CFUniCharGetLongCharacterForSurrogatePair(*(--buffer), currentChar);
--length;
} else {
break;
}
}
if (!CFUniCharIsMemberOf(currentChar, kCFUniCharNonBaseCharacterSet)) break;
property = CFUniCharGetCombiningPropertyForCharacter(currentChar, CFUniCharGetUnicodePropertyDataForPlane(kCFUniCharCombiningProperty, (currentChar >> 16) & 0xFF));
if (property == 230) return false; }
if (length == 0) {
currentChar = *(--buffer);
} else if (CFUniCharIsSurrogateLowCharacter(currentChar) && CFUniCharIsSurrogateHighCharacter(*(--buffer))) {
currentChar = CFUniCharGetLongCharacterForSurrogatePair(*buffer, currentChar);
}
decompLength = CFUniCharDecomposeCharacter(currentChar, decomposed, MAX_DECOMPOSED_LENGTH);
currentChar = *decomposed;
for (idx = 1;idx < decompLength;idx++) {
currentChar = decomposed[idx];
property = CFUniCharGetCombiningPropertyForCharacter(currentChar, CFUniCharGetUnicodePropertyDataForPlane(kCFUniCharCombiningProperty, (currentChar >> 16) & 0xFF));
if (property == 230) return false; }
return true;
}
__private_extern__ uint32_t CFUniCharGetConditionalCaseMappingFlags(UTF32Char theChar, UTF16Char *buffer, uint32_t currentIndex, uint32_t length, uint32_t type, const uint8_t *langCode, uint32_t lastFlags) {
if (theChar == 0x03A3) { if ((type == kCFUniCharToLowercase) && (currentIndex > 0)) {
UTF16Char *start = buffer;
UTF16Char *end = buffer + length;
UTF32Char otherChar;
buffer += (currentIndex - 1);
while (start <= buffer) {
otherChar = *(buffer--);
if (CFUniCharIsSurrogateLowCharacter(otherChar) && (start <= buffer) && CFUniCharIsSurrogateHighCharacter(*buffer)) {
otherChar = CFUniCharGetLongCharacterForSurrogatePair(*(buffer--), otherChar);
}
if (!CFUniCharIsMemberOf(otherChar, kCFUniCharCaseIgnorableCharacterSet)) {
if (!CFUniCharIsMemberOf(otherChar, kCFUniCharUppercaseLetterCharacterSet) && !CFUniCharIsMemberOf(otherChar, kCFUniCharLowercaseLetterCharacterSet)) return 0; break;
}
}
buffer = start + currentIndex + 1;
while (buffer < end) {
otherChar = *(buffer++);
if (CFUniCharIsSurrogateHighCharacter(otherChar) && (buffer < end) && CFUniCharIsSurrogateLowCharacter(*buffer)) {
otherChar = CFUniCharGetLongCharacterForSurrogatePair(otherChar, *(buffer++));
}
if (!CFUniCharIsMemberOf(otherChar, kCFUniCharCaseIgnorableCharacterSet)) {
if (CFUniCharIsMemberOf(otherChar, kCFUniCharUppercaseLetterCharacterSet) || CFUniCharIsMemberOf(otherChar, kCFUniCharLowercaseLetterCharacterSet)) return 0; break;
}
}
return kCFUniCharCaseMapFinalSigma;
}
} else if (langCode) {
if (*((const uint16_t *)langCode) == LITHUANIAN_LANG_CODE) {
if ((theChar == 0x0307) && ((kCFUniCharCaseMapAfter_i|kCFUniCharCaseMapMoreAbove) & lastFlags) == (kCFUniCharCaseMapAfter_i|kCFUniCharCaseMapMoreAbove)) {
return (__CFUniCharIsAfter_i(buffer, currentIndex) ? kCFUniCharCaseMapAfter_i : 0);
} else if (type == kCFUniCharToLowercase) {
if ((theChar == 0x0049) || (theChar == 0x004A) || (theChar == 0x012E)) {
return (__CFUniCharIsMoreAbove(buffer + (++currentIndex), length - currentIndex) ? kCFUniCharCaseMapMoreAbove : 0);
}
} else if ((theChar == 'i') || (theChar == 'j')) {
return (__CFUniCharIsMoreAbove(buffer + (++currentIndex), length - currentIndex) ? (kCFUniCharCaseMapAfter_i|kCFUniCharCaseMapMoreAbove) : 0);
}
} else if ((*((const uint16_t *)langCode) == TURKISH_LANG_CODE) || (*((const uint16_t *)langCode) == AZERI_LANG_CODE)) {
if (type == kCFUniCharToLowercase) {
if (theChar == 0x0307) {
return (kCFUniCharCaseMapMoreAbove & lastFlags ? kCFUniCharCaseMapAfter_i : 0);
} else if (theChar == 0x0049) {
return (((++currentIndex < length) && (buffer[currentIndex] == 0x0307)) ? kCFUniCharCaseMapMoreAbove : 0);
}
}
}
}
return 0;
}
static __CFUniCharBitmapData *__CFUniCharUnicodePropertyTable = NULL;
static int __CFUniCharUnicodePropertyTableCount = 0;
static CFSpinLock_t __CFUniCharPropTableLock = 0;
#define PROP_DB_FILE "CFUniCharPropertyDatabase.data"
const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint32_t plane) {
__CFSpinLock(&__CFUniCharPropTableLock);
if (NULL == __CFUniCharUnicodePropertyTable) {
const void *bytes;
const void *bodyBase;
const void *planeBase;
int headerSize;
int idx, count;
int planeIndex, planeCount;
int planeSize;
if (!__CFUniCharLoadFile(PROP_DB_FILE, &bytes)) {
__CFSpinUnlock(&__CFUniCharPropTableLock);
return NULL;
}
(char *)bytes += 4; headerSize = CFSwapInt32BigToHost(*(((uint32_t *)bytes)++));
headerSize -= (sizeof(uint32_t) * 2);
bodyBase = (char *)bytes + headerSize;
count = headerSize / sizeof(uint32_t);
__CFUniCharUnicodePropertyTableCount = count;
__CFUniCharUnicodePropertyTable = (__CFUniCharBitmapData *)CFAllocatorAllocate(NULL, sizeof(__CFUniCharBitmapData) * count, 0);
for (idx = 0;idx < count;idx++) {
planeCount = *((const uint8_t *)bodyBase);
(char *)planeBase = (char *)bodyBase + planeCount + (planeCount % 4 ? 4 - (planeCount % 4) : 0);
__CFUniCharUnicodePropertyTable[idx]._planes = (const uint8_t **)CFAllocatorAllocate(NULL, sizeof(const void *) * planeCount, 0);
for (planeIndex = 0;planeIndex < planeCount;planeIndex++) {
if ((planeSize = ((const uint8_t *)bodyBase)[planeIndex + 1])) {
__CFUniCharUnicodePropertyTable[idx]._planes[planeIndex] = planeBase;
(char *)planeBase += (planeSize * 256);
} else {
__CFUniCharUnicodePropertyTable[idx]._planes[planeIndex] = NULL;
}
}
__CFUniCharUnicodePropertyTable[idx]._numPlanes = planeCount;
(char *)bodyBase += (CFSwapInt32BigToHost(*(((uint32_t *)bytes)++)));
}
}
__CFSpinUnlock(&__CFUniCharPropTableLock);
return (plane < __CFUniCharUnicodePropertyTable[propertyType]._numPlanes ? __CFUniCharUnicodePropertyTable[propertyType]._planes[plane] : NULL);
}
__private_extern__ uint32_t CFUniCharGetNumberOfPlanesForUnicodePropertyData(uint32_t propertyType) {
(void)CFUniCharGetUnicodePropertyDataForPlane(propertyType, 0);
return __CFUniCharUnicodePropertyTable[propertyType]._numPlanes;
}
__private_extern__ uint32_t CFUniCharGetUnicodeProperty(UTF32Char character, uint32_t propertyType) {
if (propertyType == kCFUniCharCombiningProperty) {
return CFUniCharGetCombiningPropertyForCharacter(character, CFUniCharGetUnicodePropertyDataForPlane(propertyType, (character >> 16) & 0xFF));
} else if (propertyType == kCFUniCharBidiProperty) {
return CFUniCharGetBidiPropertyForCharacter(character, CFUniCharGetUnicodePropertyDataForPlane(propertyType, (character >> 16) & 0xFF));
} else {
return 0;
}
}
#define UNI_REPLACEMENT_CHAR (0x0000FFFDUL)
bool CFUniCharFillDestinationBuffer(const UTF32Char *src, uint32_t srcLength, void **dst, uint32_t dstLength, uint32_t *filledLength, uint32_t dstFormat) {
UTF32Char currentChar;
uint32_t usedLength = *filledLength;
if (dstFormat == kCFUniCharUTF16Format) {
UTF16Char *dstBuffer = (UTF16Char *)*dst;
while (srcLength-- > 0) {
currentChar = *(src++);
if (currentChar > 0xFFFF) { usedLength += 2;
if (dstLength) {
if (usedLength > dstLength) return false;
currentChar -= 0x10000;
*(dstBuffer++) = (UTF16Char)((currentChar >> 10) + 0xD800UL);
*(dstBuffer++) = (UTF16Char)((currentChar & 0x3FF) + 0xDC00UL);
}
} else {
++usedLength;
if (dstLength) {
if (usedLength > dstLength) return false;
*(dstBuffer++) = (UTF16Char)currentChar;
}
}
}
*dst = dstBuffer;
} else if (dstFormat == kCFUniCharUTF8Format) {
uint8_t *dstBuffer = (uint8_t *)*dst;
uint16_t bytesToWrite = 0;
const UTF32Char byteMask = 0xBF;
const UTF32Char byteMark = 0x80;
static const uint8_t firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
while (srcLength-- > 0) {
currentChar = *(src++);
if (currentChar < (UTF32Char)0x80) {
bytesToWrite = 1;
} else if (currentChar < (UTF32Char)0x800) {
bytesToWrite = 2;
} else if (currentChar < (UTF32Char)0x10000) {
bytesToWrite = 3;
} else if (currentChar < (UTF32Char)0x200000) {
bytesToWrite = 4;
} else {
bytesToWrite = 2;
currentChar = UNI_REPLACEMENT_CHAR;
}
usedLength += bytesToWrite;
if (dstLength) {
if (usedLength > dstLength) return false;
dstBuffer += bytesToWrite;
switch (bytesToWrite) {
case 4: *--dstBuffer = (currentChar | byteMark) & byteMask; currentChar >>= 6;
case 3: *--dstBuffer = (currentChar | byteMark) & byteMask; currentChar >>= 6;
case 2: *--dstBuffer = (currentChar | byteMark) & byteMask; currentChar >>= 6;
case 1: *--dstBuffer = currentChar | firstByteMark[bytesToWrite];
}
dstBuffer += bytesToWrite;
}
}
*dst = dstBuffer;
} else {
UTF32Char *dstBuffer = (UTF32Char *)*dst;
while (srcLength-- > 0) {
currentChar = *(src++);
++usedLength;
if (dstLength) {
if (usedLength > dstLength) return false;
*(dstBuffer++) = currentChar;
}
}
*dst = dstBuffer;
}
*filledLength = usedLength;
return true;
}
#if defined(__WIN32__)
void __CFUniCharCleanup(void)
{
int idx;
__CFSpinLock(&__CFUniCharBitmapLock);
if (__CFUniCharBitmapDataArray != NULL) {
for (idx = 0; idx < __CFUniCharNumberOfBitmaps; idx++) {
CFAllocatorDeallocate(NULL, __CFUniCharBitmapDataArray[idx]._planes);
__CFUniCharBitmapDataArray[idx]._planes = NULL;
}
CFAllocatorDeallocate(NULL, __CFUniCharBitmapDataArray);
__CFUniCharBitmapDataArray = NULL;
__CFUniCharNumberOfBitmaps = 0;
}
__CFSpinUnlock(&__CFUniCharBitmapLock);
__CFSpinLock(&__CFUniCharMappingTableLock);
if (__CFUniCharMappingTables != NULL) {
CFAllocatorDeallocate(NULL, __CFUniCharMappingTables);
__CFUniCharMappingTables = NULL;
}
if (__CFUniCharCaseMappingTableCounts != NULL) {
CFAllocatorDeallocate(NULL, __CFUniCharCaseMappingTableCounts);
__CFUniCharCaseMappingTableCounts = NULL;
__CFUniCharCaseMappingTable = NULL;
__CFUniCharCaseMappingExtraTable = NULL;
}
__CFSpinUnlock(&__CFUniCharMappingTableLock);
__CFSpinLock(&__CFUniCharPropTableLock);
if (__CFUniCharUnicodePropertyTable != NULL) {
for (idx = 0; idx < __CFUniCharUnicodePropertyTableCount; idx++) {
CFAllocatorDeallocate(NULL, __CFUniCharUnicodePropertyTable[idx]._planes);
__CFUniCharUnicodePropertyTable[idx]._planes = NULL;
}
CFAllocatorDeallocate(NULL, __CFUniCharUnicodePropertyTable);
__CFUniCharUnicodePropertyTable = NULL;
__CFUniCharUnicodePropertyTableCount = 0;
}
__CFSpinUnlock(&__CFUniCharPropTableLock);
}
#endif // __WIN32__