/* * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* CFCharacterSet.c Copyright 1999-2002, Apple, Inc. All rights reserved. Responsibility: Aki Inoue */ #include #include #include "CFCharacterSetPriv.h" #include #include #include "CFInternal.h" #include "CFUniChar.h" #include "CFUniCharPriv.h" #include #include #if !defined(__MACOS8__) #define __MACOS8__ 0 #endif #define BITSPERBYTE 8 /* (CHAR_BIT * sizeof(unsigned char)) */ #define LOG_BPB 3 #define LOG_BPLW 5 #define NUMCHARACTERS 65536 #define MAX_ANNEX_PLANE (16) /* Number of things in the array keeping the bits. */ #define __kCFBitmapSize (NUMCHARACTERS / BITSPERBYTE) /* How many elements max can be in an __kCFCharSetClassString CFCharacterSet */ #define __kCFStringCharSetMax 64 /* The last builtin set ID number */ #define __kCFLastBuiltinSetID kCFCharacterSetSymbol /* How many elements in the "singles" array before we use binary search. */ #define __kCFSetBreakeven 10 /* This tells us, within 1k or so, whether a thing is POTENTIALLY in the set (in the bitmap blob of the private structure) before we bother to do specific checking. */ #define __CFCSetBitsInRange(n, i) (i[n>>15] & (1L << ((n>>10) % 32))) /* Compact bitmap params */ #define __kCFCompactBitmapNumPages (256) #define __kCFCompactBitmapMaxPages (128) // the max pages allocated #define __kCFCompactBitmapPageSize (__kCFBitmapSize / __kCFCompactBitmapNumPages) typedef struct { CFCharacterSetRef *_nonBMPPlanes; unsigned int _validEntriesBitmap; unsigned char _numOfAllocEntries; unsigned char _isAnnexInverted; uint16_t _padding; } CFCharSetAnnexStruct; struct __CFCharacterSet { CFRuntimeBase _base; CFHashCode _hashValue; union { struct { CFIndex _type; } _builtin; struct { UInt32 _firstChar; CFIndex _length; } _range; struct { UniChar *_buffer; CFIndex _length; } _string; struct { uint8_t *_bits; } _bitmap; struct { uint8_t *_cBits; } _compactBitmap; } _variants; CFCharSetAnnexStruct *_annex; }; /* _base._info values interesting for CFCharacterSet */ enum { __kCFCharSetClassTypeMask = 0x0070, __kCFCharSetClassBuiltin = 0x0000, __kCFCharSetClassRange = 0x0010, __kCFCharSetClassString = 0x0020, __kCFCharSetClassBitmap = 0x0030, __kCFCharSetClassSet = 0x0040, __kCFCharSetClassCompactBitmap = 0x0040, __kCFCharSetIsInvertedMask = 0x0008, __kCFCharSetIsInverted = 0x0008, __kCFCharSetHasHashValueMask = 0x00004, __kCFCharSetHasHashValue = 0x0004, /* Generic CFBase values */ __kCFCharSetIsMutableMask = 0x0001, __kCFCharSetIsMutable = 0x0001, }; /* Inline accessor macros for _base._info */ CF_INLINE Boolean __CFCSetIsMutable(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetIsMutableMask) == __kCFCharSetIsMutable;} CF_INLINE Boolean __CFCSetIsBuiltin(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetClassTypeMask) == __kCFCharSetClassBuiltin;} CF_INLINE Boolean __CFCSetIsRange(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetClassTypeMask) == __kCFCharSetClassRange;} CF_INLINE Boolean __CFCSetIsString(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetClassTypeMask) == __kCFCharSetClassString;} CF_INLINE Boolean __CFCSetIsBitmap(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetClassTypeMask) == __kCFCharSetClassBitmap;} CF_INLINE Boolean __CFCSetIsCompactBitmap(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetClassTypeMask) == __kCFCharSetClassCompactBitmap;} CF_INLINE Boolean __CFCSetIsInverted(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetIsInvertedMask) == __kCFCharSetIsInverted;} CF_INLINE Boolean __CFCSetHasHashValue(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetHasHashValueMask) == __kCFCharSetHasHashValue;} CF_INLINE UInt32 __CFCSetClassType(CFCharacterSetRef cset) {return (cset->_base._info & __kCFCharSetClassTypeMask);} CF_INLINE void __CFCSetPutIsMutable(CFMutableCharacterSetRef cset, Boolean isMutable) {(isMutable ? (cset->_base._info |= __kCFCharSetIsMutable) : (cset->_base._info &= ~ __kCFCharSetIsMutable));} CF_INLINE void __CFCSetPutIsInverted(CFMutableCharacterSetRef cset, Boolean isInverted) {(isInverted ? (cset->_base._info |= __kCFCharSetIsInverted) : (cset->_base._info &= ~__kCFCharSetIsInverted));} CF_INLINE void __CFCSetPutHasHashValue(CFMutableCharacterSetRef cset, Boolean hasHash) {(hasHash ? (cset->_base._info |= __kCFCharSetHasHashValue) : (cset->_base._info &= ~__kCFCharSetHasHashValue));} CF_INLINE void __CFCSetPutClassType(CFMutableCharacterSetRef cset, UInt32 classType) {cset->_base._info &= ~__kCFCharSetClassTypeMask; cset->_base._info |= classType;} /* Inline contents accessor macros */ CF_INLINE CFCharacterSetPredefinedSet __CFCSetBuiltinType(CFCharacterSetRef cset) {return cset->_variants._builtin._type;} CF_INLINE UInt32 __CFCSetRangeFirstChar(CFCharacterSetRef cset) {return cset->_variants._range._firstChar;} CF_INLINE CFIndex __CFCSetRangeLength(CFCharacterSetRef cset) {return cset->_variants._range._length;} CF_INLINE UniChar *__CFCSetStringBuffer(CFCharacterSetRef cset) {return (UniChar*)(cset->_variants._string._buffer);} CF_INLINE CFIndex __CFCSetStringLength(CFCharacterSetRef cset) {return cset->_variants._string._length;} CF_INLINE uint8_t *__CFCSetBitmapBits(CFCharacterSetRef cset) {return cset->_variants._bitmap._bits;} CF_INLINE uint8_t *__CFCSetCompactBitmapBits(CFCharacterSetRef cset) {return cset->_variants._compactBitmap._cBits;} CF_INLINE void __CFCSetPutBuiltinType(CFMutableCharacterSetRef cset, CFCharacterSetPredefinedSet type) {cset->_variants._builtin._type = type;} CF_INLINE void __CFCSetPutRangeFirstChar(CFMutableCharacterSetRef cset, UInt32 first) {cset->_variants._range._firstChar = first;} CF_INLINE void __CFCSetPutRangeLength(CFMutableCharacterSetRef cset, CFIndex length) {cset->_variants._range._length = length;} CF_INLINE void __CFCSetPutStringBuffer(CFMutableCharacterSetRef cset, UniChar *theBuffer) {cset->_variants._string._buffer = theBuffer;} CF_INLINE void __CFCSetPutStringLength(CFMutableCharacterSetRef cset, CFIndex length) {cset->_variants._string._length = length;} CF_INLINE void __CFCSetPutBitmapBits(CFMutableCharacterSetRef cset, uint8_t *bits) {cset->_variants._bitmap._bits = bits;} CF_INLINE void __CFCSetPutCompactBitmapBits(CFMutableCharacterSetRef cset, uint8_t *bits) {cset->_variants._compactBitmap._cBits = bits;} /* Validation funcs */ #if defined(CF_ENABLE_ASSERTIONS) CF_INLINE void __CFCSetValidateBuiltinType(CFCharacterSetPredefinedSet type, const char *func) { CFAssert2(type > 0 && type <= __kCFLastBuiltinSetID, __kCFLogAssertion, "%s: Unknowen builtin type %d", func, type); } CF_INLINE void __CFCSetValidateRange(CFRange theRange, const char *func) { CFAssert3(theRange.location >= 0 && theRange.location + theRange.length <= 0x1FFFFF, __kCFLogAssertion, "%s: Range out of Unicode range (location -> %d length -> %d)", func, theRange.location, theRange.length); } CF_INLINE void __CFCSetValidateTypeAndMutability(CFCharacterSetRef cset, const char *func) { __CFGenericValidateType(cset, __kCFCharacterSetTypeID); CFAssert1(__CFCSetIsMutable(cset), __kCFLogAssertion, "%s: Immutable character set passed to mutable function", func); } #else #define __CFCSetValidateBuiltinType(t,f) #define __CFCSetValidateRange(r,f) #define __CFCSetValidateTypeAndMutability(r,f) #endif /* Inline utility funcs */ static Boolean __CFCSetIsEqualBitmap(const UInt32 *bits1, const UInt32 *bits2) { CFIndex length = __kCFBitmapSize / sizeof(UInt32); if (bits1 == bits2) { return true; } else if (bits1 && bits2) { if (bits1 == (const UInt32 *)-1) { while (length--) if ((UInt32)-1 != *bits2++) return false; } else if (bits2 == (const UInt32 *)-1) { while (length--) if ((UInt32)-1 != *bits1++) return false; } else { while (length--) if (*bits1++ != *bits2++) return false; } return true; } else if (!bits1 && !bits2) { // empty set return true; } else { if (bits2) bits1 = bits2; if (bits1 == (const UInt32 *)-1) return false; while (length--) if (*bits1++) return false; return true; } } CF_INLINE Boolean __CFCSetIsEqualBitmapInverted(const UInt32 *bits1, const UInt32 *bits2) { CFIndex length = __kCFBitmapSize / sizeof(UInt32); while (length--) if (*bits1++ != ~(*(bits2++))) return false; return true; } static Boolean __CFCSetIsBitmapEqualToRange(const UInt32 *bits, UniChar firstChar, UniChar lastChar, Boolean isInverted) { CFIndex firstCharIndex = firstChar >> LOG_BPB; CFIndex lastCharIndex = lastChar >> LOG_BPB; CFIndex length; UInt32 value; if (firstCharIndex == lastCharIndex) { value = ((((UInt32)0xFF) << (firstChar & (BITSPERBYTE - 1))) & (((UInt32)0xFF) >> ((BITSPERBYTE - 1) - (lastChar & (BITSPERBYTE - 1))))) << (((sizeof(UInt32) - 1) - (firstCharIndex % sizeof(UInt32))) * BITSPERBYTE); value = CFSwapInt32HostToBig(value); firstCharIndex = lastCharIndex = firstChar >> LOG_BPLW; if (*(bits + firstCharIndex) != (isInverted ? ~value : value)) return FALSE; } else { UInt32 firstCharMask; UInt32 lastCharMask; length = firstCharIndex % sizeof(UInt32); firstCharMask = (((((UInt32)0xFF) << (firstChar & (BITSPERBYTE - 1))) & 0xFF) << (((sizeof(UInt32) - 1) - length) * BITSPERBYTE)) | (0xFFFFFFFF >> ((length + 1) * BITSPERBYTE)); length = lastCharIndex % sizeof(UInt32); lastCharMask = ((((UInt32)0xFF) >> ((BITSPERBYTE - 1) - (lastChar & (BITSPERBYTE - 1)))) << (((sizeof(UInt32) - 1) - length) * BITSPERBYTE)) | (0xFFFFFFFF << ((sizeof(UInt32) - length) * BITSPERBYTE)); firstCharIndex = firstChar >> LOG_BPLW; lastCharIndex = lastChar >> LOG_BPLW; if (firstCharIndex == lastCharIndex) { firstCharMask &= lastCharMask; value = CFSwapInt32HostToBig(firstCharMask & lastCharMask); if (*(bits + firstCharIndex) != (isInverted ? ~value : value)) return FALSE; } else { value = CFSwapInt32HostToBig(firstCharMask); if (*(bits + firstCharIndex) != (isInverted ? ~value : value)) return FALSE; value = CFSwapInt32HostToBig(lastCharMask); if (*(bits + lastCharIndex) != (isInverted ? ~value : value)) return FALSE; } } length = firstCharIndex; value = (isInverted ? 0xFFFFFFFF : 0); while (length--) { if (*(bits++) != value) return FALSE; } ++bits; // Skip firstCharIndex length = (lastCharIndex - (firstCharIndex + 1)); value = (isInverted ? 0 : 0xFFFFFFFF); while (length-- > 0) { if (*(bits++) != value) return FALSE; } if (firstCharIndex != lastCharIndex) ++bits; length = (0xFFFF >> LOG_BPLW) - lastCharIndex; value = (isInverted ? 0xFFFFFFFF : 0); while (length--) { if (*(bits++) != value) return FALSE; } return TRUE; } CF_INLINE Boolean __CFCSetIsBitmapSupersetOfBitmap(const UInt32 *bits1, const UInt32 *bits2, Boolean isInverted1, Boolean isInverted2) { CFIndex length = __kCFBitmapSize / sizeof(UInt32); UInt32 val1, val2; while (length--) { val2 = (isInverted2 ? ~(*(bits2++)) : *(bits2++)); val1 = (isInverted1 ? ~(*(bits1++)) : *(bits1++)) & val2; if (val1 != val2) return false; } return true; } CF_INLINE Boolean __CFCSetHasNonBMPPlane(CFCharacterSetRef cset) { return ((cset)->_annex && (cset)->_annex->_validEntriesBitmap ? true : false); } CF_INLINE Boolean __CFCSetAnnexIsInverted (CFCharacterSetRef cset) { return ((cset)->_annex && (cset)->_annex->_isAnnexInverted ? true : false); } CF_INLINE UInt32 __CFCSetAnnexValidEntriesBitmap(CFCharacterSetRef cset) { return ((cset)->_annex && (cset)->_annex->_validEntriesBitmap ? (cset)->_annex->_validEntriesBitmap : 0); } CF_INLINE Boolean __CFCSetIsEmpty(CFCharacterSetRef cset) { if (__CFCSetHasNonBMPPlane(cset) || __CFCSetAnnexIsInverted(cset)) return false; switch (__CFCSetClassType(cset)) { case __kCFCharSetClassRange: if (!__CFCSetRangeLength(cset)) return true; break; case __kCFCharSetClassString: if (!__CFCSetStringLength(cset)) return true; break; case __kCFCharSetClassBitmap: if (!__CFCSetBitmapBits(cset)) return true; break; case __kCFCharSetClassCompactBitmap: if (!__CFCSetCompactBitmapBits(cset)) return true; break; } return false; } CF_INLINE void __CFCSetBitmapAddCharacter(uint8_t *bitmap, UniChar theChar) { bitmap[(theChar) >> LOG_BPB] |= (((unsigned)1) << (theChar & (BITSPERBYTE - 1))); } CF_INLINE void __CFCSetBitmapRemoveCharacter(uint8_t *bitmap, UniChar theChar) { bitmap[(theChar) >> LOG_BPB] &= ~(((unsigned)1) << (theChar & (BITSPERBYTE - 1))); } CF_INLINE Boolean __CFCSetIsMemberBitmap(const uint8_t *bitmap, UniChar theChar) { return ((bitmap[(theChar) >> LOG_BPB] & (((unsigned)1) << (theChar & (BITSPERBYTE - 1)))) ? true : false); } #define NUM_32BIT_SLOTS (NUMCHARACTERS / 32) CF_INLINE void __CFCSetBitmapFastFillWithValue(UInt32 *bitmap, uint8_t value) { UInt32 mask = (value << 24) | (value << 16) | (value << 8) | value; UInt32 numSlots = NUMCHARACTERS / 32; while (numSlots--) *(bitmap++) = mask; } CF_INLINE void __CFCSetBitmapAddCharactersInRange(uint8_t *bitmap, UniChar firstChar, UniChar lastChar) { if (firstChar == lastChar) { bitmap[firstChar >> LOG_BPB] |= (((unsigned)1) << (firstChar & (BITSPERBYTE - 1))); } else { UInt32 idx = firstChar >> LOG_BPB; UInt32 max = lastChar >> LOG_BPB; if (idx == max) { bitmap[idx] |= (((unsigned)0xFF) << (firstChar & (BITSPERBYTE - 1))) & (((unsigned)0xFF) >> ((BITSPERBYTE - 1) - (lastChar & (BITSPERBYTE - 1)))); } else { bitmap[idx] |= (((unsigned)0xFF) << (firstChar & (BITSPERBYTE - 1))); bitmap[max] |= (((unsigned)0xFF) >> ((BITSPERBYTE - 1) - (lastChar & (BITSPERBYTE - 1)))); ++idx; while (idx < max) bitmap[idx++] = 0xFF; } } } CF_INLINE void __CFCSetBitmapRemoveCharactersInRange(uint8_t *bitmap, UniChar firstChar, UniChar lastChar) { UInt32 idx = firstChar >> LOG_BPB; UInt32 max = lastChar >> LOG_BPB; if (idx == max) { bitmap[idx] &= ~((((unsigned)0xFF) << (firstChar & (BITSPERBYTE - 1))) & (((unsigned)0xFF) >> ((BITSPERBYTE - 1) - (lastChar & (BITSPERBYTE - 1))))); } else { bitmap[idx] &= ~(((unsigned)0xFF) << (firstChar & (BITSPERBYTE - 1))); bitmap[max] &= ~(((unsigned)0xFF) >> ((BITSPERBYTE - 1) - (lastChar & (BITSPERBYTE - 1)))); ++idx; while (idx < max) bitmap[idx++] = 0; } } #define __CFCSetAnnexBitmapSetPlane(bitmap,plane) ((bitmap) |= (1 << (plane))) #define __CFCSetAnnexBitmapClearPlane(bitmap,plane) ((bitmap) &= (~(1 << (plane)))) #define __CFCSetAnnexBitmapGetPlane(bitmap,plane) ((bitmap) & (1 << (plane))) CF_INLINE void __CFCSetAnnexSetIsInverted(CFCharacterSetRef cset, Boolean flag) { if (cset->_annex) ((CFMutableCharacterSetRef)cset)->_annex->_isAnnexInverted = flag; } CF_INLINE void __CFCSetAllocateAnnexForPlane(CFCharacterSetRef cset, int plane) { if (cset->_annex == NULL) { ((CFMutableCharacterSetRef)cset)->_annex = (CFCharSetAnnexStruct *)CFAllocatorAllocate(CFGetAllocator(cset), sizeof(CFCharSetAnnexStruct), 0); cset->_annex->_numOfAllocEntries = plane; cset->_annex->_isAnnexInverted = false; cset->_annex->_validEntriesBitmap = 0; cset->_annex->_nonBMPPlanes = (CFCharacterSetRef*)CFAllocatorAllocate(CFGetAllocator(cset), sizeof(CFCharacterSetRef) * plane, 0); } else if (cset->_annex->_numOfAllocEntries < plane) { cset->_annex->_numOfAllocEntries = plane; cset->_annex->_nonBMPPlanes = (CFCharacterSetRef*)CFAllocatorReallocate(CFGetAllocator(cset), (void *)cset->_annex->_nonBMPPlanes, sizeof(CFCharacterSetRef) * plane, 0); } } CF_INLINE void __CFCSetPutCharacterSetToAnnexPlane(CFCharacterSetRef cset, CFCharacterSetRef annexCSet, int plane) { __CFCSetAllocateAnnexForPlane(cset, plane); if (__CFCSetAnnexBitmapGetPlane(cset->_annex->_validEntriesBitmap, plane)) CFRelease(cset->_annex->_nonBMPPlanes[plane - 1]); if (annexCSet) { cset->_annex->_nonBMPPlanes[plane - 1] = CFRetain(annexCSet); __CFCSetAnnexBitmapSetPlane(cset->_annex->_validEntriesBitmap, plane); } else { __CFCSetAnnexBitmapClearPlane(cset->_annex->_validEntriesBitmap, plane); } } CF_INLINE CFCharacterSetRef __CFCSetGetAnnexPlaneCharacterSet(CFCharacterSetRef cset, int plane) { __CFCSetAllocateAnnexForPlane(cset, plane); if (!__CFCSetAnnexBitmapGetPlane(cset->_annex->_validEntriesBitmap, plane)) { cset->_annex->_nonBMPPlanes[plane - 1] = (CFCharacterSetRef)CFCharacterSetCreateMutable(CFGetAllocator(cset)); __CFCSetAnnexBitmapSetPlane(cset->_annex->_validEntriesBitmap, plane); } return cset->_annex->_nonBMPPlanes[plane - 1]; } CF_INLINE CFCharacterSetRef __CFCSetGetAnnexPlaneCharacterSetNoAlloc(CFCharacterSetRef cset, int plane) { return (cset->_annex && __CFCSetAnnexBitmapGetPlane(cset->_annex->_validEntriesBitmap, plane) ? cset->_annex->_nonBMPPlanes[plane - 1] : NULL); } CF_INLINE void __CFCSetDeallocateAnnexPlane(CFCharacterSetRef cset) { if (cset->_annex) { int idx; for (idx = 0;idx < MAX_ANNEX_PLANE;idx++) { if (__CFCSetAnnexBitmapGetPlane(cset->_annex->_validEntriesBitmap, idx + 1)) { CFRelease(cset->_annex->_nonBMPPlanes[idx]); } } CFAllocatorDeallocate(CFGetAllocator(cset), cset->_annex->_nonBMPPlanes); CFAllocatorDeallocate(CFGetAllocator(cset), cset->_annex); ((CFMutableCharacterSetRef)cset)->_annex = NULL; } } CF_INLINE uint8_t __CFCSetGetHeaderValue(const uint8_t *bitmap, int *numPages) { uint8_t value = *bitmap; if ((value == 0) || (value == UINT8_MAX)) { int numBytes = __kCFCompactBitmapPageSize - 1; while (numBytes > 0) { if (*(++bitmap) != value) break; --numBytes; } if (numBytes == 0) return value; } return (uint8_t)(++(*numPages)); } CF_INLINE bool __CFCSetIsMemberInCompactBitmap(const uint8_t *compactBitmap, UTF16Char character) { uint8_t value = compactBitmap[(character >> 8)]; // Assuming __kCFCompactBitmapNumPages == 256 if (value == 0) { return false; } else if (value == UINT8_MAX) { return true; } else { compactBitmap += (__kCFCompactBitmapNumPages + (__kCFCompactBitmapPageSize * (value - 1))); character &= 0xFF; // Assuming __kCFCompactBitmapNumPages == 256 return ((compactBitmap[(character / BITSPERBYTE)] & (1 << (character % BITSPERBYTE))) ? true : false); } } CF_INLINE uint32_t __CFCSetGetCompactBitmapSize(const uint8_t *compactBitmap) { uint32_t length = __kCFCompactBitmapNumPages; uint32_t size = __kCFCompactBitmapNumPages; uint8_t value; while (length-- > 0) { value = *(compactBitmap++); if ((value != 0) && (value != UINT8_MAX)) size += __kCFCompactBitmapPageSize; } return size; } /* Take a private "set" structure and make a bitmap from it. Return the bitmap. THE CALLER MUST RELEASE THE RETURNED MEMORY as necessary. */ CF_INLINE void __CFCSetBitmapProcessManyCharacters(unsigned char *map, unsigned n, unsigned m, Boolean isInverted) { if (isInverted) { __CFCSetBitmapRemoveCharactersInRange(map, n, m); } else { __CFCSetBitmapAddCharactersInRange(map, n, m); } } CF_INLINE void __CFExpandCompactBitmap(const uint8_t *src, uint8_t *dst) { const uint8_t *srcBody = src + __kCFCompactBitmapNumPages; int i; uint8_t value; for (i = 0;i < __kCFCompactBitmapNumPages;i++) { value = *(src++); if ((value == 0) || (value == UINT8_MAX)) { memset(dst, value, __kCFCompactBitmapPageSize); } else { memmove(dst, srcBody, __kCFCompactBitmapPageSize); srcBody += __kCFCompactBitmapPageSize; } dst += __kCFCompactBitmapPageSize; } } static void __CFCheckForExpandedSet(CFCharacterSetRef cset) { static int8_t __CFNumberOfPlanesForLogging = -1; static bool warnedOnce = false; if (0 > __CFNumberOfPlanesForLogging) { const char *envVar = getenv("CFCharacterSetCheckForExpandedSet"); long value = (envVar ? strtol(envVar, NULL, 0) : 0); __CFNumberOfPlanesForLogging = (((value > 0) && (value <= 16)) ? value : 0); } if (__CFNumberOfPlanesForLogging) { uint32_t entries = __CFCSetAnnexValidEntriesBitmap(cset); int count = 0; while (entries) { if ((entries & 1) && (++count >= __CFNumberOfPlanesForLogging)) { if (!warnedOnce) { CFLog(0, CFSTR("An expanded CFMutableCharacter has been detected. Recommend to compact with CFCharacterSetCreateCopy")); warnedOnce = true; } break; } entries >>= 1; } } } static void __CFCSetGetBitmap(CFCharacterSetRef cset, uint8_t *bits) { uint8_t *bitmap; CFIndex length = __kCFBitmapSize; if (__CFCSetIsBitmap(cset) && (bitmap = __CFCSetBitmapBits(cset))) { memmove(bits, bitmap, __kCFBitmapSize); } else { Boolean isInverted = __CFCSetIsInverted(cset); uint8_t value = (isInverted ? (uint8_t)-1 : 0); bitmap = bits; while (length--) *bitmap++ = value; // Initialize the buffer if (!__CFCSetIsEmpty(cset)) { switch (__CFCSetClassType(cset)) { case __kCFCharSetClassBuiltin: { UInt8 result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(cset), 0, bits, isInverted); if (result == kCFUniCharBitmapEmpty && isInverted) { length = __kCFBitmapSize; bitmap = bits; while (length--) *bitmap++ = 0; } else if (result == kCFUniCharBitmapAll && !isInverted) { length = __kCFBitmapSize; bitmap = bits; while (length--) *bitmap++ = (UInt8)0xFF; } } break; case __kCFCharSetClassRange: { UInt32 theChar = __CFCSetRangeFirstChar(cset); if (theChar < NUMCHARACTERS) { // the range starts in BMP length = __CFCSetRangeLength(cset); if (theChar + length >= NUMCHARACTERS) length = NUMCHARACTERS - theChar; if (isInverted) { __CFCSetBitmapRemoveCharactersInRange(bits, theChar, (theChar + length) - 1); } else { __CFCSetBitmapAddCharactersInRange(bits, theChar, (theChar + length) - 1); } } } break; case __kCFCharSetClassString: { const UniChar *buffer = __CFCSetStringBuffer(cset); length = __CFCSetStringLength(cset); while (length--) (isInverted ? __CFCSetBitmapRemoveCharacter(bits, *buffer++) : __CFCSetBitmapAddCharacter(bits, *buffer++)); } break; case __kCFCharSetClassCompactBitmap: __CFExpandCompactBitmap(__CFCSetCompactBitmapBits(cset), bits); break; } } } } static Boolean __CFCharacterSetEqual(CFTypeRef cf1, CFTypeRef cf2); static Boolean __CFCSetIsEqualAnnex(CFCharacterSetRef cf1, CFCharacterSetRef cf2) { CFCharacterSetRef subSet1; CFCharacterSetRef subSet2; Boolean isAnnexInvertStateIdentical = (__CFCSetAnnexIsInverted(cf1) == __CFCSetAnnexIsInverted(cf2) ? true: false); int idx; if (isAnnexInvertStateIdentical) { if (__CFCSetAnnexValidEntriesBitmap(cf1) != __CFCSetAnnexValidEntriesBitmap(cf2)) return false; for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { subSet1 = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(cf1, idx); subSet2 = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(cf2, idx); if (subSet1 && !__CFCharacterSetEqual(subSet1, subSet2)) return false; } } else { uint8_t bitsBuf[__kCFBitmapSize]; #if __MACOS8__ uint8_t *bitsBuf2 = NULL; #else __MACOS8__ uint8_t bitsBuf2[__kCFBitmapSize]; #endif __MACOS8__ for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { subSet1 = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(cf1, idx); subSet2 = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(cf2, idx); if (subSet1 == NULL && subSet2 == NULL) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } else if (subSet1 == NULL) { if (__CFCSetIsBitmap(subSet2)) { if (!__CFCSetIsEqualBitmap((const UInt32 *)__CFCSetBitmapBits(subSet2), (const UInt32 *)-1)) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } } else { __CFCSetGetBitmap(subSet2, bitsBuf); if (!__CFCSetIsEqualBitmap((const UInt32 *)bitsBuf, (const UInt32 *)-1)) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } } } else if (subSet2 == NULL) { if (__CFCSetIsBitmap(subSet1)) { if (!__CFCSetIsEqualBitmap((const UInt32 *)__CFCSetBitmapBits(subSet1), (const UInt32 *)-1)) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } } else { __CFCSetGetBitmap(subSet1, bitsBuf); if (!__CFCSetIsEqualBitmap((const UInt32 *)bitsBuf, (const UInt32 *)-1)) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } } } else { Boolean isBitmap1 = __CFCSetIsBitmap(subSet1); Boolean isBitmap2 = __CFCSetIsBitmap(subSet2); if (isBitmap1 && isBitmap2) { if (!__CFCSetIsEqualBitmapInverted((const UInt32 *)__CFCSetBitmapBits(subSet1), (const UInt32 *)__CFCSetBitmapBits(subSet2))) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } } else if (!isBitmap1 && !isBitmap2) { __CFCSetGetBitmap(subSet1, bitsBuf); #if __MACOS8__ if (bitsBuf2 == NULL) bitsBuf2 = (UInt32 *)CFAllocatorAllocate(NULL, __kCFBitmapSize, 0); #endif __MACOS8__ __CFCSetGetBitmap(subSet2, bitsBuf2); if (!__CFCSetIsEqualBitmapInverted((const UInt32 *)bitsBuf, (const UInt32 *)bitsBuf2)) { #if __MACOS8__ CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } } else { if (isBitmap2) { CFCharacterSetRef tmp = subSet2; subSet2 = subSet1; subSet1 = tmp; } __CFCSetGetBitmap(subSet2, bitsBuf); if (!__CFCSetIsEqualBitmapInverted((const UInt32 *)__CFCSetBitmapBits(subSet1), (const UInt32 *)bitsBuf)) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } } } } } return true; } /* Compact bitmap */ static uint8_t *__CFCreateCompactBitmap(CFAllocatorRef allocator, const uint8_t *bitmap) { const uint8_t *src; uint8_t *dst; int i; int numPages = 0; uint8_t header[__kCFCompactBitmapNumPages]; src = bitmap; for (i = 0;i < __kCFCompactBitmapNumPages;i++) { header[i] = __CFCSetGetHeaderValue(src, &numPages); // Allocating more pages is probably not interesting enough to be compact if (numPages > __kCFCompactBitmapMaxPages) return NULL; src += __kCFCompactBitmapPageSize; } dst = (uint8_t *)CFAllocatorAllocate(allocator, __kCFCompactBitmapNumPages + (__kCFCompactBitmapPageSize * numPages), AUTO_MEMORY_UNSCANNED); if (numPages > 0) { uint8_t *dstBody = dst + __kCFCompactBitmapNumPages; src = bitmap; for (i = 0;i < __kCFCompactBitmapNumPages;i++) { dst[i] = header[i]; if ((dst[i] != 0) && (dst[i] != UINT8_MAX)) { memmove(dstBody, src, __kCFCompactBitmapPageSize); dstBody += __kCFCompactBitmapPageSize; } src += __kCFCompactBitmapPageSize; } } else { memmove(dst, header, __kCFCompactBitmapNumPages); } return dst; } static void __CFCSetMakeCompact(CFMutableCharacterSetRef cset) { if (__CFCSetIsBitmap(cset) && __CFCSetBitmapBits(cset)) { uint8_t *bitmap = __CFCSetBitmapBits(cset); uint8_t *cBitmap = __CFCreateCompactBitmap(CFGetAllocator(cset), bitmap); if (cBitmap) { CFAllocatorDeallocate(CFGetAllocator(cset), bitmap); __CFCSetPutClassType(cset, __kCFCharSetClassCompactBitmap); __CFCSetPutCompactBitmapBits(cset, cBitmap); } } } static void __CFCSetAddNonBMPPlanesInRange(CFMutableCharacterSetRef cset, CFRange range) { int firstChar = (range.location & 0xFFFF); int maxChar = range.location + range.length; int idx = range.location >> 16; // first plane int maxPlane = (maxChar - 1) >> 16; // last plane CFRange planeRange; CFMutableCharacterSetRef annexPlane; maxChar &= 0xFFFF; for (idx = (idx ? idx : 1);idx <= maxPlane;idx++) { planeRange.location = __CFMax(firstChar, 0); planeRange.length = (idx == maxPlane && maxChar ? maxChar : 0x10000) - planeRange.location; if (__CFCSetAnnexIsInverted(cset)) { if ((annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(cset, idx))) { CFCharacterSetRemoveCharactersInRange(annexPlane, planeRange); if (__CFCSetIsEmpty(annexPlane) && !__CFCSetIsInverted(annexPlane)) { CFRelease(annexPlane); __CFCSetAnnexBitmapClearPlane(cset->_annex->_validEntriesBitmap, idx); } } } else { CFCharacterSetAddCharactersInRange((CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(cset, idx), planeRange); } } if (!__CFCSetHasNonBMPPlane(cset) && !__CFCSetAnnexIsInverted(cset)) __CFCSetDeallocateAnnexPlane(cset); } static void __CFCSetRemoveNonBMPPlanesInRange(CFMutableCharacterSetRef cset, CFRange range) { int firstChar = (range.location & 0xFFFF); int maxChar = range.location + range.length; int idx = range.location >> 16; // first plane int maxPlane = (maxChar - 1) >> 16; // last plane CFRange planeRange; CFMutableCharacterSetRef annexPlane; maxChar &= 0xFFFF; for (idx = (idx ? idx : 1);idx <= maxPlane;idx++) { planeRange.location = __CFMax(firstChar, 0); planeRange.length = (idx == maxPlane && maxChar ? maxChar : 0x10000) - planeRange.location; if (__CFCSetAnnexIsInverted(cset)) { CFCharacterSetAddCharactersInRange((CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(cset, idx), planeRange); } else { if ((annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(cset, idx))) { CFCharacterSetRemoveCharactersInRange(annexPlane, planeRange); if(__CFCSetIsEmpty(annexPlane) && !__CFCSetIsInverted(annexPlane)) { CFRelease(annexPlane); __CFCSetAnnexBitmapClearPlane(cset->_annex->_validEntriesBitmap, idx); } } } } if (!__CFCSetHasNonBMPPlane(cset) && !__CFCSetAnnexIsInverted(cset)) __CFCSetDeallocateAnnexPlane(cset); } static void __CFCSetMakeBitmap(CFMutableCharacterSetRef cset) { if (!__CFCSetIsBitmap(cset) || !__CFCSetBitmapBits(cset)) { CFAllocatorRef allocator = CFGetAllocator(cset); uint8_t *bitmap = CFAllocatorAllocate(allocator, __kCFBitmapSize, AUTO_MEMORY_UNSCANNED); __CFCSetGetBitmap(cset, bitmap); if (__CFCSetIsBuiltin(cset)) { CFIndex numPlanes = CFUniCharGetNumberOfPlanes(__CFCSetBuiltinType(cset)); if (numPlanes > 1) { CFMutableCharacterSetRef annexSet; uint8_t *annexBitmap = NULL; int idx; UInt8 result; __CFCSetAllocateAnnexForPlane(cset, numPlanes - 1); for (idx = 1;idx < numPlanes;idx++) { if (NULL == annexBitmap) { annexBitmap = CFAllocatorAllocate(allocator, __kCFBitmapSize, AUTO_MEMORY_UNSCANNED); } result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(cset), idx, annexBitmap, false); if (result == kCFUniCharBitmapEmpty) continue; if (result == kCFUniCharBitmapAll) { CFIndex bitmapLength = __kCFBitmapSize; uint8_t *bytes = annexBitmap; while (bitmapLength-- > 0) *(bytes++) = (uint8_t)0xFF; } annexSet = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(cset, idx); __CFCSetPutClassType(annexSet, __kCFCharSetClassBitmap); __CFCSetPutBitmapBits(annexSet, annexBitmap); __CFCSetPutIsInverted(annexSet, false); __CFCSetPutHasHashValue(annexSet, false); annexBitmap = NULL; } if (annexBitmap) CFAllocatorDeallocate(allocator, annexBitmap); } } else if (__CFCSetIsCompactBitmap(cset) && __CFCSetCompactBitmapBits(cset)) { CFAllocatorDeallocate(allocator, __CFCSetCompactBitmapBits(cset)); __CFCSetPutCompactBitmapBits(cset, NULL); } else if (__CFCSetIsString(cset) && __CFCSetStringBuffer(cset)) { CFAllocatorDeallocate(allocator, __CFCSetStringBuffer(cset)); __CFCSetPutStringBuffer(cset, NULL); } else if (__CFCSetIsRange(cset)) { // We may have to allocate annex here Boolean needsToInvert = (!__CFCSetHasNonBMPPlane(cset) && __CFCSetIsInverted(cset) ? true : false); __CFCSetAddNonBMPPlanesInRange(cset, CFRangeMake(__CFCSetRangeFirstChar(cset), __CFCSetRangeLength(cset))); if (needsToInvert) __CFCSetAnnexSetIsInverted(cset, true); } __CFCSetPutClassType(cset, __kCFCharSetClassBitmap); __CFCSetPutBitmapBits(cset, bitmap); __CFCSetPutIsInverted(cset, false); } } CF_INLINE CFMutableCharacterSetRef __CFCSetGenericCreate(CFAllocatorRef allocator, UInt32 flags) { CFMutableCharacterSetRef cset; CFIndex size = sizeof(struct __CFCharacterSet) - sizeof(CFRuntimeBase); cset = (CFMutableCharacterSetRef)_CFRuntimeCreateInstance(allocator, CFCharacterSetGetTypeID(), size, NULL); if (NULL == cset) return NULL; cset->_base._info |= flags; cset->_hashValue = 0; cset->_annex = NULL; return cset; } /* Bsearch theChar for __kCFCharSetClassString */ CF_INLINE Boolean __CFCSetBsearchUniChar(const UniChar *theTable, CFIndex length, UniChar theChar) { const UniChar *p, *q, *divider; if ((theChar < theTable[0]) || (theChar > theTable[length - 1])) return false; p = theTable; q = p + (length - 1); while (p <= q) { divider = p + ((q - p) >> 1); /* divide by 2 */ if (theChar < *divider) q = divider - 1; else if (theChar > *divider) p = divider + 1; else return true; } return false; } /* Predefined cset names Need to add entry here for new builtin types */ CONST_STRING_DECL(__kCFCSetNameControl, "") CONST_STRING_DECL(__kCFCSetNameWhitespace, "") CONST_STRING_DECL(__kCFCSetNameWhitespaceAndNewline, "") CONST_STRING_DECL(__kCFCSetNameDecimalDigit, "") CONST_STRING_DECL(__kCFCSetNameLetter, "") CONST_STRING_DECL(__kCFCSetNameLowercaseLetter, "") CONST_STRING_DECL(__kCFCSetNameUppercaseLetter, "") CONST_STRING_DECL(__kCFCSetNameNonBase, "") CONST_STRING_DECL(__kCFCSetNameDecomposable, "") CONST_STRING_DECL(__kCFCSetNameAlphaNumeric, "") CONST_STRING_DECL(__kCFCSetNamePunctuation, "") CONST_STRING_DECL(__kCFCSetNameIllegal, "") CONST_STRING_DECL(__kCFCSetNameCapitalizedLetter, "") CONST_STRING_DECL(__kCFCSetNameSymbol, "") CONST_STRING_DECL(__kCFCSetNameStringTypeFormat, "_hashValue != ((CFCharacterSetRef)cf2)->_hashValue) return false; if (__CFCSetIsEmpty(cf1) && __CFCSetIsEmpty(cf2) && !isInvertStateIdentical) return false; if (__CFCSetClassType(cf1) == __CFCSetClassType(cf2)) { // Types are identical, we can do it fast switch (__CFCSetClassType(cf1)) { case __kCFCharSetClassBuiltin: return (__CFCSetBuiltinType(cf1) == __CFCSetBuiltinType(cf2) && isInvertStateIdentical ? true : false); case __kCFCharSetClassRange: return (__CFCSetRangeFirstChar(cf1) == __CFCSetRangeFirstChar(cf2) && __CFCSetRangeLength(cf1) && __CFCSetRangeLength(cf2) && isInvertStateIdentical ? true : false); case __kCFCharSetClassString: if (__CFCSetStringLength(cf1) == __CFCSetStringLength(cf2) && isInvertStateIdentical) { const UniChar *buf1 = __CFCSetStringBuffer(cf1); const UniChar *buf2 = __CFCSetStringBuffer(cf2); CFIndex length = __CFCSetStringLength(cf1); while (length--) if (*buf1++ != *buf2++) return false; } else { return false; } break; case __kCFCharSetClassBitmap: if (!__CFCSetIsEqualBitmap((const UInt32 *)__CFCSetBitmapBits(cf1), (const UInt32 *)__CFCSetBitmapBits(cf2))) return false; break; } return __CFCSetIsEqualAnnex(cf1, cf2); } // Check for easy empty cases if (__CFCSetIsEmpty(cf1) || __CFCSetIsEmpty(cf2)) { CFCharacterSetRef emptySet = (__CFCSetIsEmpty(cf1) ? cf1 : cf2); CFCharacterSetRef nonEmptySet = (emptySet == cf1 ? cf2 : cf1); if (__CFCSetIsBuiltin(nonEmptySet)) { return false; } else if (__CFCSetIsRange(nonEmptySet)) { if (isInvertStateIdentical) { return (__CFCSetRangeLength(nonEmptySet) ? false : true); } else { return (__CFCSetRangeLength(nonEmptySet) == 0x110000 ? true : false); } } else { if (__CFCSetAnnexIsInverted(nonEmptySet)) { if (__CFCSetAnnexValidEntriesBitmap(nonEmptySet) != 0x1FFFE) return false; } else { if (__CFCSetAnnexValidEntriesBitmap(nonEmptySet)) return false; } if (__CFCSetIsBitmap(nonEmptySet)) { bits = __CFCSetBitmapBits(nonEmptySet); } else { bits = bitsBuf; __CFCSetGetBitmap(nonEmptySet, bitsBuf); } if (__CFCSetIsEqualBitmap(NULL, (const UInt32 *)bits)) { if (!__CFCSetAnnexIsInverted(nonEmptySet)) return true; } else { return false; } // Annex set has to be CFRangeMake(0x10000, 0xfffff) for (idx = 1;idx < MAX_ANNEX_PLANE;idx++) { if (__CFCSetIsBitmap(nonEmptySet)) { if (!__CFCSetIsEqualBitmap((__CFCSetAnnexIsInverted(nonEmptySet) ? NULL : (const UInt32 *)-1), (const UInt32 *)bitsBuf)) return false; } else { __CFCSetGetBitmap(__CFCSetGetAnnexPlaneCharacterSetNoAlloc(nonEmptySet, idx), bitsBuf); if (!__CFCSetIsEqualBitmap((const UInt32 *)-1, (const UInt32 *)bitsBuf)) return false; } } return true; } } if (__CFCSetIsBuiltin(cf1) || __CFCSetIsBuiltin(cf2)) { CFCharacterSetRef builtinSet = (__CFCSetIsBuiltin(cf1) ? cf1 : cf2); CFCharacterSetRef nonBuiltinSet = (builtinSet == cf1 ? cf2 : cf1); if (__CFCSetIsRange(nonBuiltinSet)) { UTF32Char firstChar = __CFCSetRangeFirstChar(nonBuiltinSet); UTF32Char lastChar = (firstChar + __CFCSetRangeLength(nonBuiltinSet) - 1); uint8_t firstPlane = (firstChar >> 16) & 0xFF; uint8_t lastPlane = (lastChar >> 16) & 0xFF; uint8_t result; for (idx = 0;idx < MAX_ANNEX_PLANE;idx++) { result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(builtinSet), idx, bitsBuf, isInvertStateIdentical); if (idx < firstPlane || idx > lastPlane) { if (result == kCFUniCharBitmapAll) { return false; } else if (result == kCFUniCharBitmapFilled) { if (!__CFCSetIsEqualBitmap(NULL, (const UInt32 *)bitsBuf)) return false; } } else if (idx > firstPlane && idx < lastPlane) { if (result == kCFUniCharBitmapEmpty) { return false; } else if (result == kCFUniCharBitmapFilled) { if (!__CFCSetIsEqualBitmap((const UInt32 *)-1, (const UInt32 *)bitsBuf)) return false; } } else { if (result == kCFUniCharBitmapEmpty) { return false; } else if (result == kCFUniCharBitmapAll) { if (idx == firstPlane) { if (((firstChar & 0xFFFF) != 0) || (firstPlane == lastPlane && ((lastChar & 0xFFFF) != 0xFFFF))) return false; } else { if (((lastChar & 0xFFFF) != 0xFFFF) || (firstPlane == lastPlane && ((firstChar & 0xFFFF) != 0))) return false; } } else { if (idx == firstPlane) { if (!__CFCSetIsBitmapEqualToRange((const UInt32 *)bitsBuf, firstChar & 0xFFFF, (firstPlane == lastPlane ? lastChar & 0xFFFF : 0xFFFF), false)) return false; } else { if (!__CFCSetIsBitmapEqualToRange((const UInt32 *)bitsBuf, (firstPlane == lastPlane ? firstChar & 0xFFFF : 0), lastChar & 0xFFFF, false)) return false; } } } } return true; } else { #if __MACOS8__ uint8_t *bitsBuf2 = NULL; #else __MACOS8__ uint8_t bitsBuf2[__kCFBitmapSize]; #endif __MACOS8__ uint8_t result; result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(builtinSet), 0, bitsBuf, __CFCSetIsInverted(builtinSet)); if (result == kCFUniCharBitmapFilled) { if (__CFCSetIsBitmap(nonBuiltinSet)) { if (!__CFCSetIsEqualBitmap((const UInt32 *)bitsBuf, (const UInt32 *)__CFCSetBitmapBits(nonBuiltinSet))) return false; } else { #if __MACOS8__ bitsBuf2 = CFAllocatorAllocate(CFGetAllocator(nonBuiltinSet), __kCFBitmapSize, 0); #endif __MACOS8__ __CFCSetGetBitmap(nonBuiltinSet, bitsBuf2); if (!__CFCSetIsEqualBitmap((const UInt32 *)bitsBuf, (const UInt32 *)bitsBuf2)) { #if __MACOS8__ CFAllocatorDeallocate(CFGetAllocator(nonBuiltinSet), bitsBuf2); #endif __MACOS8__ return false; } } } else { if (__CFCSetIsBitmap(nonBuiltinSet)) { if (!__CFCSetIsEqualBitmap((result == kCFUniCharBitmapAll ? (const UInt32*)-1 : NULL), (const UInt32 *)__CFCSetBitmapBits(nonBuiltinSet))) return false; } else { __CFCSetGetBitmap(nonBuiltinSet, bitsBuf); if (!__CFCSetIsEqualBitmap((result == kCFUniCharBitmapAll ? (const UInt32*)-1: NULL), (const UInt32 *)bitsBuf)) return false; } } isInvertStateIdentical = (__CFCSetIsInverted(builtinSet) == __CFCSetAnnexIsInverted(nonBuiltinSet) ? true : false); for (idx = 1;idx < MAX_ANNEX_PLANE;idx++) { result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(builtinSet), idx, bitsBuf, !isInvertStateIdentical); subSet1 = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(nonBuiltinSet, idx); if (result == kCFUniCharBitmapFilled) { if (NULL == subSet1) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(CFGetAllocator(nonBuiltinSet), bitsBuf2); #endif __MACOS8__ return false; } else if (__CFCSetIsBitmap(subSet1)) { if (!__CFCSetIsEqualBitmap((const UInt32*)bitsBuf, (const UInt32*)__CFCSetBitmapBits(subSet1))) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(CFGetAllocator(nonBuiltinSet), bitsBuf2); #endif __MACOS8__ return false; } } else { #if __MACOS8__ if (NULL == bitsBuf2) bitsBuf2 = CFAllocatorAllocate(CFGetAllocator(nonBuiltinSet), __kCFBitmapSize, 0); #endif __MACOS8__ __CFCSetGetBitmap(subSet1, bitsBuf2); if (!__CFCSetIsEqualBitmap((const UInt32*)bitsBuf, (const UInt32*)bitsBuf2)) { #if __MACOS8__ CFAllocatorDeallocate(CFGetAllocator(nonBuiltinSet), bitsBuf2); #endif __MACOS8__ return false; } } } else { if (NULL == subSet1) { if (result == kCFUniCharBitmapAll) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(CFGetAllocator(nonBuiltinSet), bitsBuf2); #endif __MACOS8__ return false; } } else if (__CFCSetIsBitmap(subSet1)) { if (!__CFCSetIsEqualBitmap((result == kCFUniCharBitmapAll ? (const UInt32*)-1: NULL), (const UInt32*)__CFCSetBitmapBits(subSet1))) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(CFGetAllocator(nonBuiltinSet), bitsBuf2); #endif __MACOS8__ return false; } } else { __CFCSetGetBitmap(subSet1, bitsBuf); if (!__CFCSetIsEqualBitmap((result == kCFUniCharBitmapAll ? (const UInt32*)-1: NULL), (const UInt32*)bitsBuf)) { #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(CFGetAllocator(nonBuiltinSet), bitsBuf2); #endif __MACOS8__ return false; } } } } #if __MACOS8__ if (bitsBuf2) CFAllocatorDeallocate(CFGetAllocator(nonBuiltinSet), bitsBuf2); #endif __MACOS8__ return true; } } if (__CFCSetIsRange(cf1) || __CFCSetIsRange(cf2)) { CFCharacterSetRef rangeSet = (__CFCSetIsRange(cf1) ? cf1 : cf2); CFCharacterSetRef nonRangeSet = (rangeSet == cf1 ? cf2 : cf1); UTF32Char firstChar = __CFCSetRangeFirstChar(rangeSet); UTF32Char lastChar = (firstChar + __CFCSetRangeLength(rangeSet) - 1); uint8_t firstPlane = (firstChar >> 16) & 0xFF; uint8_t lastPlane = (lastChar >> 16) & 0xFF; Boolean isRangeSetInverted = __CFCSetIsInverted(rangeSet); if (__CFCSetIsBitmap(nonRangeSet)) { bits = __CFCSetBitmapBits(nonRangeSet); } else { bits = bitsBuf; __CFCSetGetBitmap(nonRangeSet, bitsBuf); } if (firstPlane == 0) { if (!__CFCSetIsBitmapEqualToRange((const UInt32*)bits, firstChar, (lastPlane == 0 ? lastChar : 0xFFFF), isRangeSetInverted)) return false; firstPlane = 1; firstChar = 0; } else { if (!__CFCSetIsEqualBitmap((const UInt32*)bits, (isRangeSetInverted ? (const UInt32 *)-1 : NULL))) return false; firstChar &= 0xFFFF; } lastChar &= 0xFFFF; isAnnexInvertStateIdentical = (isRangeSetInverted == __CFCSetAnnexIsInverted(nonRangeSet) ? true : false); for (idx = 1;idx < MAX_ANNEX_PLANE;idx++) { subSet1 = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(nonRangeSet, idx); if (NULL == subSet1) { if (idx < firstPlane || idx > lastPlane) { if (!isAnnexInvertStateIdentical) return false; } else if (idx > firstPlane && idx < lastPlane) { if (isAnnexInvertStateIdentical) return false; } else if (idx == firstPlane) { if (isAnnexInvertStateIdentical || firstChar || (idx == lastPlane && lastChar != 0xFFFF)) return false; } else if (idx == lastPlane) { if (isAnnexInvertStateIdentical || (idx == firstPlane && firstChar) || (lastChar != 0xFFFF)) return false; } } else { if (__CFCSetIsBitmap(subSet1)) { bits = __CFCSetBitmapBits(subSet1); } else { __CFCSetGetBitmap(subSet1, bitsBuf); bits = bitsBuf; } if (idx < firstPlane || idx > lastPlane) { if (!__CFCSetIsEqualBitmap((const UInt32*)bits, (isAnnexInvertStateIdentical ? NULL : (const UInt32 *)-1))) return false; } else if (idx > firstPlane && idx < lastPlane) { if (!__CFCSetIsEqualBitmap((const UInt32*)bits, (isAnnexInvertStateIdentical ? (const UInt32 *)-1 : NULL))) return false; } else if (idx == firstPlane) { if (!__CFCSetIsBitmapEqualToRange((const UInt32*)bits, firstChar, (idx == lastPlane ? lastChar : 0xFFFF), !isAnnexInvertStateIdentical)) return false; } else if (idx == lastPlane) { if (!__CFCSetIsBitmapEqualToRange((const UInt32*)bits, (idx == firstPlane ? firstChar : 0), lastChar, !isAnnexInvertStateIdentical)) return false; } } } return true; } isBitmap1 = __CFCSetIsBitmap(cf1); isBitmap2 = __CFCSetIsBitmap(cf2); if (isBitmap1 && isBitmap2) { if (!__CFCSetIsEqualBitmap((const UInt32*)__CFCSetBitmapBits(cf1), (const UInt32*)__CFCSetBitmapBits(cf2))) return false; } else if (!isBitmap1 && !isBitmap2) { #if __MACOS8__ uint8_t *bitsBuf2 = (uint8_t *)CFAllocatorAllocate(NULL, __kCFBitmapSize, 0); #else __MACOS8__ uint8_t bitsBuf2[__kCFBitmapSize]; #endif __MACOS8__ __CFCSetGetBitmap(cf1, bitsBuf); __CFCSetGetBitmap(cf2, bitsBuf2); if (!__CFCSetIsEqualBitmap((const UInt32*)bitsBuf, (const UInt32*)bitsBuf2)) { #if __MACOS8__ CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ return false; } #if __MACOS8__ CFAllocatorDeallocate(NULL, bitsBuf2); #endif __MACOS8__ } else { if (isBitmap2) { CFCharacterSetRef tmp = cf2; cf2 = cf1; cf1 = tmp; } __CFCSetGetBitmap(cf2, bitsBuf); if (!__CFCSetIsEqualBitmap((const UInt32*)__CFCSetBitmapBits(cf1), (const UInt32*)bitsBuf)) return false; } return __CFCSetIsEqualAnnex(cf1, cf2); } static CFHashCode __CFCharacterSetHash(CFTypeRef cf) { if (!__CFCSetHasHashValue(cf)) { if (__CFCSetIsEmpty(cf)) { ((CFMutableCharacterSetRef)cf)->_hashValue = (__CFCSetIsInverted(cf) ? 0xFFFFFFFF : 0); } else if (__CFCSetIsBitmap(cf)) { ((CFMutableCharacterSetRef)cf)->_hashValue = CFHashBytes(__CFCSetBitmapBits(cf), __kCFBitmapSize); } else { uint8_t bitsBuf[__kCFBitmapSize]; __CFCSetGetBitmap(cf, bitsBuf); ((CFMutableCharacterSetRef)cf)->_hashValue = CFHashBytes(bitsBuf, __kCFBitmapSize); } __CFCSetPutHasHashValue((CFMutableCharacterSetRef)cf, true); } return ((CFCharacterSetRef)cf)->_hashValue; } static CFStringRef __CFCharacterSetCopyDescription(CFTypeRef cf) { CFMutableStringRef string; CFIndex idx; CFIndex length; if (__CFCSetIsEmpty(cf)) { return (__CFCSetIsInverted(cf) ? CFRetain(CFSTR("")) : CFRetain(CFSTR(""))); } switch (__CFCSetClassType(cf)) { case __kCFCharSetClassBuiltin: switch (__CFCSetBuiltinType(cf)) { case kCFCharacterSetControl: return CFRetain(__kCFCSetNameControl); case kCFCharacterSetWhitespace : return CFRetain(__kCFCSetNameWhitespace); case kCFCharacterSetWhitespaceAndNewline: return CFRetain(__kCFCSetNameWhitespaceAndNewline); case kCFCharacterSetDecimalDigit: return CFRetain(__kCFCSetNameDecimalDigit); case kCFCharacterSetLetter: return CFRetain(__kCFCSetNameLetter); case kCFCharacterSetLowercaseLetter: return CFRetain(__kCFCSetNameLowercaseLetter); case kCFCharacterSetUppercaseLetter: return CFRetain(__kCFCSetNameUppercaseLetter); case kCFCharacterSetNonBase: return CFRetain(__kCFCSetNameNonBase); case kCFCharacterSetDecomposable: return CFRetain(__kCFCSetNameDecomposable); case kCFCharacterSetAlphaNumeric: return CFRetain(__kCFCSetNameAlphaNumeric); case kCFCharacterSetPunctuation: return CFRetain(__kCFCSetNamePunctuation); case kCFCharacterSetIllegal: return CFRetain(__kCFCSetNameIllegal); case kCFCharacterSetCapitalizedLetter: return CFRetain(__kCFCSetNameCapitalizedLetter); case kCFCharacterSetSymbol: return CFRetain(__kCFCSetNameSymbol); } break; case __kCFCharSetClassRange: return CFStringCreateWithFormat(CFGetAllocator(cf), NULL, CFSTR(""), __CFCSetRangeFirstChar(cf), __CFCSetRangeLength(cf)); case __kCFCharSetClassString: length = __CFCSetStringLength(cf); string = CFStringCreateMutable(CFGetAllocator(cf), CFStringGetLength(__kCFCSetNameStringTypeFormat) + 7 * length + 2); // length of__kCFCSetNameStringTypeFormat + "U+XXXX "(7) * length + ")>"(2) CFStringAppend(string, __kCFCSetNameStringTypeFormat); for (idx = 0;idx < length;idx++) { CFStringAppendFormat(string, NULL, CFSTR("%sU+%04X"), (idx > 0 ? " " : ""), (UInt32)((__CFCSetStringBuffer(cf))[idx])); } CFStringAppend(string, CFSTR(")>")); return string; case __kCFCharSetClassBitmap: case __kCFCharSetClassCompactBitmap: return CFRetain(CFSTR("")); // ??? Should generate description for 8k bitmap ? } CFAssert1(0, __kCFLogAssertion, "%s: Internal inconsistency error: unknown character set type", __PRETTY_FUNCTION__); // We should never come here return NULL; } static void __CFCharacterSetDeallocate(CFTypeRef cf) { CFAllocatorRef allocator = CFGetAllocator(cf); if (__CFCSetIsBuiltin(cf) && !__CFCSetIsMutable(cf) && !__CFCSetIsInverted(cf)) { CFCharacterSetRef sharedSet = CFCharacterSetGetPredefined(__CFCSetBuiltinType(cf)); if (sharedSet == cf) { // We're trying to dealloc the builtin set CFAssert1(0, __kCFLogAssertion, "%s: Trying to deallocate predefined set", __PRETTY_FUNCTION__); return; // We never deallocate builtin set } } if (__CFCSetIsString(cf) && __CFCSetStringBuffer(cf)) CFAllocatorDeallocate(allocator, __CFCSetStringBuffer(cf)); else if (__CFCSetIsBitmap(cf) && __CFCSetBitmapBits(cf)) CFAllocatorDeallocate(allocator, __CFCSetBitmapBits(cf)); else if (__CFCSetIsCompactBitmap(cf) && __CFCSetCompactBitmapBits(cf)) CFAllocatorDeallocate(allocator, __CFCSetCompactBitmapBits(cf)); __CFCSetDeallocateAnnexPlane(cf); } static CFTypeID __kCFCharacterSetTypeID = _kCFRuntimeNotATypeID; static const CFRuntimeClass __CFCharacterSetClass = { 0, "CFCharacterSet", NULL, // init NULL, // copy __CFCharacterSetDeallocate, __CFCharacterSetEqual, __CFCharacterSetHash, NULL, // __CFCharacterSetCopyDescription }; static bool __CFCheckForExapendedSet = false; __private_extern__ void __CFCharacterSetInitialize(void) { const char *checkForExpandedSet = getenv("__CF_DEBUG_EXPANDED_SET"); __kCFCharacterSetTypeID = _CFRuntimeRegisterClass(&__CFCharacterSetClass); if (checkForExpandedSet && (*checkForExpandedSet == 'Y')) __CFCheckForExapendedSet = true; } /* Public functions */ #if defined(__MACOS8__) CFTypeID CFCharacterSetTypeID(void) { #ifdef DEBUG CFLog(__kCFLogAssertion, CFSTR("CFCharacterSetTypeID should be CFCharacterSetGetTypeID")); #endif /* DEBUG */ return __kCFCharacterSetTypeID; } #endif /* __MACOS8__ */ CFTypeID CFCharacterSetGetTypeID(void) { return __kCFCharacterSetTypeID; } /*** CharacterSet creation ***/ /* Functions to create basic immutable characterset. */ CFCharacterSetRef CFCharacterSetGetPredefined(CFCharacterSetPredefinedSet theSetIdentifier) { CFMutableCharacterSetRef cset; __CFCSetValidateBuiltinType(theSetIdentifier, __PRETTY_FUNCTION__); if (__CFBuiltinSets && __CFBuiltinSets[theSetIdentifier - 1]) return __CFBuiltinSets[theSetIdentifier - 1]; if (!(cset = __CFCSetGenericCreate(kCFAllocatorSystemDefault, __kCFCharSetClassBuiltin))) return NULL; __CFCSetPutBuiltinType(cset, theSetIdentifier); if (!__CFBuiltinSets) { __CFSpinLock(&__CFCharacterSetLock); __CFBuiltinSets = (CFCharacterSetRef *)CFAllocatorAllocate(CFRetain(__CFGetDefaultAllocator()), sizeof(CFCharacterSetRef) * __kCFLastBuiltinSetID, 0); memset(__CFBuiltinSets, 0, sizeof(CFCharacterSetRef) * __kCFLastBuiltinSetID); __CFSpinUnlock(&__CFCharacterSetLock); } __CFBuiltinSets[theSetIdentifier - 1] = cset; return cset; } CFCharacterSetRef CFCharacterSetCreateWithCharactersInRange(CFAllocatorRef allocator, CFRange theRange) { CFMutableCharacterSetRef cset; __CFCSetValidateRange(theRange, __PRETTY_FUNCTION__); if (theRange.length) { if (!(cset = __CFCSetGenericCreate(allocator, __kCFCharSetClassRange))) return NULL; __CFCSetPutRangeFirstChar(cset, theRange.location); __CFCSetPutRangeLength(cset, theRange.length); } else { if (!(cset = __CFCSetGenericCreate(allocator, __kCFCharSetClassBitmap))) return NULL; __CFCSetPutBitmapBits(cset, NULL); __CFCSetPutHasHashValue(cset, true); // _hashValue is 0 } return cset; } static int chcompar(const void *a, const void *b) { return -(int)(*(UniChar *)b - *(UniChar *)a); } CFCharacterSetRef CFCharacterSetCreateWithCharactersInString(CFAllocatorRef allocator, CFStringRef theString) { CFIndex length; length = CFStringGetLength(theString); if (length < __kCFStringCharSetMax) { CFMutableCharacterSetRef cset; if (!(cset = __CFCSetGenericCreate(allocator, __kCFCharSetClassString))) return NULL; __CFCSetPutStringBuffer(cset, CFAllocatorAllocate(CFGetAllocator(cset), __kCFStringCharSetMax * sizeof(UniChar), AUTO_MEMORY_UNSCANNED)); __CFCSetPutStringLength(cset, length); CFStringGetCharacters(theString, CFRangeMake(0, length), __CFCSetStringBuffer(cset)); qsort(__CFCSetStringBuffer(cset), length, sizeof(UniChar), chcompar); if (!length) __CFCSetPutHasHashValue(cset, true); // _hashValue is 0 return cset; } else { CFMutableCharacterSetRef mcset = CFCharacterSetCreateMutable(allocator); CFCharacterSetAddCharactersInString(mcset, theString); __CFCSetMakeCompact(mcset); __CFCSetPutIsMutable(mcset, false); return mcset; } } #if defined(__MACOS8__) CFCharacterSetRef CFCharacterSetCreateWithBitmapReresentation(CFAllocatorRef allocator, CFDataRef theData) { #ifdef DEBUG CFLog(__kCFLogAssertion, CFSTR("CFCharacterSetCreateWithBitmapReresentation should be CFCharacterSetCreateWithBitmapRepresentation")); #endif /* DEBUG */ return CFCharacterSetCreateWithBitmapRepresentation(allocator, theData); } #endif /* __MACOS8__ */ CFCharacterSetRef CFCharacterSetCreateWithBitmapRepresentation(CFAllocatorRef allocator, CFDataRef theData) { CFMutableCharacterSetRef cset; CFIndex length; if (!(cset = __CFCSetGenericCreate(allocator, __kCFCharSetClassBitmap))) return NULL; if (theData && (length = CFDataGetLength(theData)) > 0) { uint8_t *bitmap; uint8_t *cBitmap; if (length < __kCFBitmapSize) { bitmap = (uint8_t *)CFAllocatorAllocate(allocator, __kCFBitmapSize, AUTO_MEMORY_UNSCANNED); memmove(bitmap, CFDataGetBytePtr(theData), length); memset(bitmap + length, 0, __kCFBitmapSize - length); cBitmap = __CFCreateCompactBitmap(allocator, bitmap); if (cBitmap == NULL) { __CFCSetPutBitmapBits(cset, bitmap); } else { CFAllocatorDeallocate(allocator, bitmap); __CFCSetPutCompactBitmapBits(cset, cBitmap); __CFCSetPutClassType(cset, __kCFCharSetClassCompactBitmap); } } else { cBitmap = __CFCreateCompactBitmap(allocator, CFDataGetBytePtr(theData)); if (cBitmap == NULL) { bitmap = (uint8_t *)CFAllocatorAllocate(allocator, __kCFBitmapSize, AUTO_MEMORY_UNSCANNED); memmove(bitmap, CFDataGetBytePtr(theData), __kCFBitmapSize); __CFCSetPutBitmapBits(cset, bitmap); } else { __CFCSetPutCompactBitmapBits(cset, cBitmap); __CFCSetPutClassType(cset, __kCFCharSetClassCompactBitmap); } if (length > __kCFBitmapSize) { CFMutableCharacterSetRef annexSet; const char *bytes = CFDataGetBytePtr(theData) + __kCFBitmapSize; length -= __kCFBitmapSize; while (length > 1) { annexSet = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(cset, *(bytes++)); --length; // Decrement the plane no byte if (length < __kCFBitmapSize) { bitmap = (uint8_t *)CFAllocatorAllocate(allocator, __kCFBitmapSize, AUTO_MEMORY_UNSCANNED); memmove(bitmap, bytes, length); memset(bitmap + length, 0, __kCFBitmapSize - length); cBitmap = __CFCreateCompactBitmap(allocator, bitmap); if (cBitmap == NULL) { __CFCSetPutBitmapBits(annexSet, bitmap); } else { CFAllocatorDeallocate(allocator, bitmap); __CFCSetPutCompactBitmapBits(annexSet, cBitmap); __CFCSetPutClassType(annexSet, __kCFCharSetClassCompactBitmap); } } else { cBitmap = __CFCreateCompactBitmap(allocator, bytes); if (cBitmap == NULL) { bitmap = (uint8_t *)CFAllocatorAllocate(allocator, __kCFBitmapSize, AUTO_MEMORY_UNSCANNED); memmove(bitmap, bytes, __kCFBitmapSize); __CFCSetPutBitmapBits(annexSet, bitmap); } else { __CFCSetPutCompactBitmapBits(annexSet, cBitmap); __CFCSetPutClassType(annexSet, __kCFCharSetClassCompactBitmap); } } length -= __kCFBitmapSize; bytes += __kCFBitmapSize; } } } } else { __CFCSetPutBitmapBits(cset, NULL); __CFCSetPutHasHashValue(cset, true); // Hash value is 0 } return cset; } CFCharacterSetRef CFCharacterSetCreateInvertedSet(CFAllocatorRef alloc, CFCharacterSetRef theSet) { CFMutableCharacterSetRef cset; CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFCharacterSetRef , theSet, "invertedSet"); cset = CFCharacterSetCreateMutableCopy(alloc, theSet); CFCharacterSetInvert(cset); __CFCSetPutIsMutable(cset, false); return cset; } /* Functions to create mutable characterset. */ CFMutableCharacterSetRef CFCharacterSetCreateMutable(CFAllocatorRef allocator) { CFMutableCharacterSetRef cset; if (!(cset = __CFCSetGenericCreate(allocator, __kCFCharSetClassBitmap| __kCFCharSetIsMutable))) return NULL; __CFCSetPutBitmapBits(cset, NULL); __CFCSetPutHasHashValue(cset, true); // Hash value is 0 return cset; } CFMutableCharacterSetRef __CFCharacterSetCreateCopy(CFAllocatorRef alloc, CFCharacterSetRef theSet, bool isMutable) { CFMutableCharacterSetRef cset; CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFMutableCharacterSetRef , theSet, "mutableCopy"); __CFGenericValidateType(theSet, __kCFCharacterSetTypeID); if (!isMutable && !__CFCSetIsMutable(theSet)) { return (CFMutableCharacterSetRef)CFRetain(theSet); } cset = CFCharacterSetCreateMutable(alloc); __CFCSetPutClassType(cset, __CFCSetClassType(theSet)); __CFCSetPutHasHashValue(cset, __CFCSetHasHashValue(theSet)); __CFCSetPutIsInverted(cset, __CFCSetIsInverted(theSet)); cset->_hashValue = theSet->_hashValue; switch (__CFCSetClassType(theSet)) { case __kCFCharSetClassBuiltin: __CFCSetPutBuiltinType(cset, __CFCSetBuiltinType(theSet)); break; case __kCFCharSetClassRange: __CFCSetPutRangeFirstChar(cset, __CFCSetRangeFirstChar(theSet)); __CFCSetPutRangeLength(cset, __CFCSetRangeLength(theSet)); break; case __kCFCharSetClassString: __CFCSetPutStringBuffer(cset, CFAllocatorAllocate(alloc, __kCFStringCharSetMax * sizeof(UniChar), AUTO_MEMORY_UNSCANNED)); __CFCSetPutStringLength(cset, __CFCSetStringLength(theSet)); memmove(__CFCSetStringBuffer(cset), __CFCSetStringBuffer(theSet), __CFCSetStringLength(theSet) * sizeof(UniChar)); break; case __kCFCharSetClassBitmap: if (__CFCSetBitmapBits(theSet)) { uint8_t * bitmap = (isMutable ? NULL : __CFCreateCompactBitmap(alloc, __CFCSetBitmapBits(theSet))); if (bitmap == NULL) { bitmap = (uint8_t *)CFAllocatorAllocate(alloc, sizeof(uint8_t) * __kCFBitmapSize, AUTO_MEMORY_UNSCANNED); memmove(bitmap, __CFCSetBitmapBits(theSet), __kCFBitmapSize); __CFCSetPutBitmapBits(cset, bitmap); } else { __CFCSetPutCompactBitmapBits(cset, bitmap); __CFCSetPutClassType(cset, __kCFCharSetClassCompactBitmap); } } else { __CFCSetPutBitmapBits(cset, NULL); } break; case __kCFCharSetClassCompactBitmap: { const uint8_t *compactBitmap = __CFCSetCompactBitmapBits(theSet); if (compactBitmap) { uint32_t size = __CFCSetGetCompactBitmapSize(compactBitmap); uint8_t *newBitmap = (uint8_t *)CFAllocatorAllocate(alloc, size, AUTO_MEMORY_UNSCANNED); memmove(newBitmap, compactBitmap, size); __CFCSetPutCompactBitmapBits(cset, newBitmap); } } break; default: CFAssert1(0, __kCFLogAssertion, "%s: Internal inconsistency error: unknown character set type", __PRETTY_FUNCTION__); // We should never come here } if (__CFCSetHasNonBMPPlane(theSet)) { CFMutableCharacterSetRef annexPlane; int idx; for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx))) { annexPlane = __CFCharacterSetCreateCopy(alloc, annexPlane, isMutable); __CFCSetPutCharacterSetToAnnexPlane(cset, annexPlane, idx); CFRelease(annexPlane); } } __CFCSetAnnexSetIsInverted(cset, __CFCSetAnnexIsInverted(theSet)); } else if (__CFCSetAnnexIsInverted(theSet)) { __CFCSetAllocateAnnexForPlane(cset, 0); // We need to alloc annex to invert __CFCSetAnnexSetIsInverted(cset, true); } return cset; } CFCharacterSetRef CFCharacterSetCreateCopy(CFAllocatorRef alloc, CFCharacterSetRef theSet) { return __CFCharacterSetCreateCopy(alloc, theSet, false); } CFMutableCharacterSetRef CFCharacterSetCreateMutableCopy(CFAllocatorRef alloc, CFCharacterSetRef theSet) { return __CFCharacterSetCreateCopy(alloc, theSet, true); } /*** Basic accessors ***/ Boolean CFCharacterSetIsCharacterMember(CFCharacterSetRef theSet, UniChar theChar) { return CFCharacterSetIsLongCharacterMember(theSet, theChar); } Boolean CFCharacterSetIsLongCharacterMember(CFCharacterSetRef theSet, UTF32Char theChar) { CFIndex length; UInt32 plane = (theChar >> 16); Boolean isAnnexInverted = false; Boolean isInverted; Boolean result = false; CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, Boolean, theSet, "longCharacterIsMember:", theChar); __CFGenericValidateType(theSet, __kCFCharacterSetTypeID); if (plane) { CFCharacterSetRef annexPlane; if (__CFCSetIsBuiltin(theSet)) { isInverted = __CFCSetIsInverted(theSet); return (CFUniCharIsMemberOf(theChar, __CFCSetBuiltinType(theSet)) ? !isInverted : isInverted); } isAnnexInverted = __CFCSetAnnexIsInverted(theSet); if ((annexPlane = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, plane)) == NULL) { if (!__CFCSetHasNonBMPPlane(theSet) && __CFCSetIsRange(theSet)) { isInverted = __CFCSetIsInverted(theSet); length = __CFCSetRangeLength(theSet); return (length && __CFCSetRangeFirstChar(theSet) <= theChar && theChar < __CFCSetRangeFirstChar(theSet) + length ? !isInverted : isInverted); } else { return (isAnnexInverted ? true : false); } } else { theSet = annexPlane; theChar &= 0xFFFF; } } isInverted = __CFCSetIsInverted(theSet); switch (__CFCSetClassType(theSet)) { case __kCFCharSetClassBuiltin: result = (CFUniCharIsMemberOf(theChar, __CFCSetBuiltinType(theSet)) ? !isInverted : isInverted); break; case __kCFCharSetClassRange: length = __CFCSetRangeLength(theSet); result = (length && __CFCSetRangeFirstChar(theSet) <= theChar && theChar < __CFCSetRangeFirstChar(theSet) + length ? !isInverted : isInverted); break; case __kCFCharSetClassString: result = ((length = __CFCSetStringLength(theSet)) ? (__CFCSetBsearchUniChar(__CFCSetStringBuffer(theSet), length, theChar) ? !isInverted : isInverted) : isInverted); break; case __kCFCharSetClassBitmap: result = (__CFCSetCompactBitmapBits(theSet) ? (__CFCSetIsMemberBitmap(__CFCSetBitmapBits(theSet), theChar) ? true : false) : isInverted); break; case __kCFCharSetClassCompactBitmap: result = (__CFCSetCompactBitmapBits(theSet) ? (__CFCSetIsMemberInCompactBitmap(__CFCSetCompactBitmapBits(theSet), theChar) ? true : false) : isInverted); break; default: CFAssert1(0, __kCFLogAssertion, "%s: Internal inconsistency error: unknown character set type", __PRETTY_FUNCTION__); // We should never come here return false; // To make compiler happy } return (result ? !isAnnexInverted : isAnnexInverted); } Boolean CFCharacterSetIsSurrogatePairMember(CFCharacterSetRef theSet, UniChar surrogateHigh, UniChar surrogateLow) { return CFCharacterSetIsLongCharacterMember(theSet, CFCharacterSetGetLongCharacterForSurrogatePair(surrogateHigh, surrogateLow)); } static CFCharacterSetRef __CFCharacterSetGetExpandedSetForNSCharacterSet(const void *characterSet) { CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFCharacterSetRef , characterSet, "_expandedCFCharacterSet"); return NULL; } Boolean CFCharacterSetIsSupersetOfSet(CFCharacterSetRef theSet, CFCharacterSetRef theOtherSet) { CFMutableCharacterSetRef copy; CFCharacterSetRef expandedSet = NULL; CFCharacterSetRef expandedOtherSet = NULL; Boolean result; if ((!CF_IS_OBJC(__kCFCharacterSetTypeID, theSet) || (expandedSet = __CFCharacterSetGetExpandedSetForNSCharacterSet(theSet))) && (!CF_IS_OBJC(__kCFCharacterSetTypeID, theOtherSet) || (expandedOtherSet = __CFCharacterSetGetExpandedSetForNSCharacterSet(theOtherSet)))) { // Really CF, we can do some trick here if (expandedSet) theSet = expandedSet; if (expandedOtherSet) theOtherSet = expandedOtherSet; __CFGenericValidateType(theSet, __kCFCharacterSetTypeID); __CFGenericValidateType(theOtherSet, __kCFCharacterSetTypeID); if (__CFCSetIsEmpty(theSet)) { if (__CFCSetIsInverted(theSet)) { return TRUE; // Inverted empty set covers all range } else if (!__CFCSetIsEmpty(theOtherSet) || __CFCSetIsInverted(theOtherSet)) { return FALSE; } } else if (__CFCSetIsEmpty(theOtherSet) && !__CFCSetIsInverted(theOtherSet)) { return TRUE; } else { if (__CFCSetIsBuiltin(theSet) || __CFCSetIsBuiltin(theOtherSet)) { if (__CFCSetClassType(theSet) == __CFCSetClassType(theOtherSet) && __CFCSetBuiltinType(theSet) == __CFCSetBuiltinType(theOtherSet) && !__CFCSetIsInverted(theSet) && !__CFCSetIsInverted(theOtherSet)) return TRUE; } else if (__CFCSetIsRange(theSet) || __CFCSetIsRange(theOtherSet)) { if (__CFCSetClassType(theSet) == __CFCSetClassType(theOtherSet)) { if (__CFCSetIsInverted(theSet)) { if (__CFCSetIsInverted(theOtherSet)) { return (__CFCSetRangeFirstChar(theOtherSet) > __CFCSetRangeFirstChar(theSet) || (__CFCSetRangeFirstChar(theSet) + __CFCSetRangeLength(theSet)) > (__CFCSetRangeFirstChar(theOtherSet) + __CFCSetRangeLength(theOtherSet)) ? FALSE : TRUE); } else { return ((__CFCSetRangeFirstChar(theOtherSet) + __CFCSetRangeLength(theOtherSet)) <= __CFCSetRangeFirstChar(theSet) || (__CFCSetRangeFirstChar(theSet) + __CFCSetRangeLength(theSet)) <= __CFCSetRangeFirstChar(theOtherSet) ? TRUE : FALSE); } } else { if (__CFCSetIsInverted(theOtherSet)) { return ((__CFCSetRangeFirstChar(theSet) == 0 && __CFCSetRangeLength(theSet) == 0x110000) || (__CFCSetRangeFirstChar(theOtherSet) == 0 && (UInt32)__CFCSetRangeLength(theOtherSet) <= __CFCSetRangeFirstChar(theSet)) || ((__CFCSetRangeFirstChar(theSet) + __CFCSetRangeLength(theSet)) <= __CFCSetRangeFirstChar(theOtherSet) && (__CFCSetRangeFirstChar(theOtherSet) + __CFCSetRangeLength(theOtherSet)) == 0x110000) ? TRUE : FALSE); } else { return (__CFCSetRangeFirstChar(theOtherSet) < __CFCSetRangeFirstChar(theSet) || (__CFCSetRangeFirstChar(theSet) + __CFCSetRangeLength(theSet)) < (__CFCSetRangeFirstChar(theOtherSet) + __CFCSetRangeLength(theOtherSet)) ? FALSE : TRUE); } } } } else { UInt32 theSetAnnexMask = __CFCSetAnnexValidEntriesBitmap(theSet); UInt32 theOtherSetAnnexMask = __CFCSetAnnexValidEntriesBitmap(theOtherSet); Boolean isTheSetAnnexInverted = __CFCSetAnnexIsInverted(theSet); Boolean isTheOtherSetAnnexInverted = __CFCSetAnnexIsInverted(theOtherSet); uint8_t theSetBuffer[__kCFBitmapSize]; uint8_t theOtherSetBuffer[__kCFBitmapSize]; // We mask plane 1 to plane 16 if (isTheSetAnnexInverted) theSetAnnexMask = (~theSetAnnexMask) & (0xFFFF < 1); if (isTheOtherSetAnnexInverted) theOtherSetAnnexMask = (~theOtherSetAnnexMask) & (0xFFFF < 1); __CFCSetGetBitmap(theSet, theSetBuffer); __CFCSetGetBitmap(theOtherSet, theOtherSetBuffer); if (!__CFCSetIsBitmapSupersetOfBitmap((const UInt32 *)theSetBuffer, (const UInt32 *)theOtherSetBuffer, FALSE, FALSE)) return FALSE; if (theOtherSetAnnexMask) { CFCharacterSetRef theSetAnnex; CFCharacterSetRef theOtherSetAnnex; uint32_t idx; if ((theSetAnnexMask & theOtherSetAnnexMask) != theOtherSetAnnexMask) return FALSE; for (idx = 1;idx <= 16;idx++) { theSetAnnex = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx); if (NULL == theSetAnnex) continue; // This case is already handled by the mask above theOtherSetAnnex = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(theOtherSet, idx); if (NULL == theOtherSetAnnex) { if (isTheOtherSetAnnexInverted) { __CFCSetGetBitmap(theSetAnnex, theSetBuffer); if (!__CFCSetIsEqualBitmap((const UInt32 *)theSetBuffer, (isTheSetAnnexInverted ? NULL : (const UInt32 *)-1))) return FALSE; } } else { __CFCSetGetBitmap(theSetAnnex, theSetBuffer); __CFCSetGetBitmap(theOtherSetAnnex, theOtherSetBuffer); if (!__CFCSetIsBitmapSupersetOfBitmap((const UInt32 *)theSetBuffer, (const UInt32 *)theOtherSetBuffer, isTheSetAnnexInverted, isTheOtherSetAnnexInverted)) return FALSE; } } } return TRUE; } } } copy = CFCharacterSetCreateMutableCopy(NULL, theSet); CFCharacterSetIntersect(copy, theOtherSet); result = __CFCharacterSetEqual(copy, theOtherSet); CFRelease(copy); return result; } Boolean CFCharacterSetHasMemberInPlane(CFCharacterSetRef theSet, CFIndex thePlane) { Boolean isInverted = __CFCSetIsInverted(theSet); CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, Boolean, theSet, "hasMemberInPlane:", thePlane); if (__CFCSetIsEmpty(theSet)) { return (isInverted ? TRUE : FALSE); } else if (__CFCSetIsBuiltin(theSet)) { CFCharacterSetPredefinedSet type = __CFCSetBuiltinType(theSet); if (type == kCFCharacterSetControl) { if (isInverted || (thePlane == 14)) { return TRUE; // There is no plane that covers all values || Plane 14 has language tags } else { return (CFUniCharGetBitmapPtrForPlane(type, thePlane) ? TRUE : FALSE); } } else if (type < kCFCharacterSetDecimalDigit) { return (thePlane && !isInverted ? FALSE : TRUE); } else if (__CFCSetBuiltinType(theSet) == kCFCharacterSetIllegal) { return (isInverted ? (thePlane < 3 || thePlane > 13 ? TRUE : FALSE) : TRUE); // This is according to Unicode 3.1 } else { if (isInverted) { return TRUE; // There is no plane that covers all values } else { return (CFUniCharGetBitmapPtrForPlane(type, thePlane) ? TRUE : FALSE); } } } else if (__CFCSetIsRange(theSet)) { UTF32Char firstChar = __CFCSetRangeFirstChar(theSet); UTF32Char lastChar = (firstChar + __CFCSetRangeLength(theSet) - 1); CFIndex firstPlane = firstChar >> 16; CFIndex lastPlane = lastChar >> 16; if (isInverted) { if (thePlane < firstPlane || thePlane > lastPlane) { return TRUE; } else if (thePlane > firstPlane && thePlane < lastPlane) { return FALSE; } else { firstChar &= 0xFFFF; lastChar &= 0xFFFF; if (thePlane == firstPlane) { return (firstChar || (firstPlane == lastPlane && lastChar != 0xFFFF) ? TRUE : FALSE); } else { return (lastChar != 0xFFFF || (firstPlane == lastPlane && firstChar) ? TRUE : FALSE); } } } else { return (thePlane < firstPlane || thePlane > lastPlane ? FALSE : TRUE); } } else { if (thePlane == 0) { switch (__CFCSetClassType(theSet)) { case __kCFCharSetClassString: if (!__CFCSetStringLength(theSet)) return isInverted; break; case __kCFCharSetClassCompactBitmap: return (__CFCSetCompactBitmapBits(theSet) ? TRUE : FALSE); break; case __kCFCharSetClassBitmap: return (__CFCSetBitmapBits(theSet) ? TRUE : FALSE); break; } return TRUE; } else { CFCharacterSetRef annex = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, thePlane); if (annex) { if (__CFCSetIsRange(annex)) { return (__CFCSetAnnexIsInverted(theSet) && (__CFCSetRangeFirstChar(annex) == 0) && (__CFCSetRangeLength(annex) == 0x10000) ? FALSE : TRUE); } else if (__CFCSetIsBitmap(annex)) { return (__CFCSetAnnexIsInverted(theSet) && __CFCSetIsEqualBitmap((const UInt32 *)__CFCSetBitmapBits(annex), (const UInt32 *)-1) ? FALSE : TRUE); } else { uint8_t bitsBuf[__kCFBitmapSize]; __CFCSetGetBitmap(annex, bitsBuf); return (__CFCSetAnnexIsInverted(theSet) && __CFCSetIsEqualBitmap((const UInt32 *)bitsBuf, (const UInt32 *)-1) ? FALSE : TRUE); } } else { return __CFCSetAnnexIsInverted(theSet); } } } return FALSE; } CFDataRef CFCharacterSetCreateBitmapRepresentation(CFAllocatorRef alloc, CFCharacterSetRef theSet) { CFMutableDataRef data; int numNonBMPPlanes = 0; int planeIndices[MAX_ANNEX_PLANE]; int idx; int length; bool isAnnexInverted; CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFDataRef , theSet, "_retainedBitmapRepresentation"); __CFGenericValidateType(theSet, __kCFCharacterSetTypeID); isAnnexInverted = __CFCSetAnnexIsInverted(theSet); if (__CFCSetHasNonBMPPlane(theSet)) { for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if (isAnnexInverted || __CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) { planeIndices[numNonBMPPlanes++] = idx; } } } else if (__CFCSetIsBuiltin(theSet)) { numNonBMPPlanes = (__CFCSetIsInverted(theSet) ? MAX_ANNEX_PLANE : CFUniCharGetNumberOfPlanes(__CFCSetBuiltinType(theSet)) - 1); } else if (__CFCSetIsRange(theSet)) { UInt32 firstChar = __CFCSetRangeFirstChar(theSet); UInt32 lastChar = __CFCSetRangeFirstChar(theSet) + __CFCSetRangeLength(theSet) - 1; int firstPlane = (firstChar >> 16); int lastPlane = (lastChar >> 16); bool isInverted = __CFCSetIsInverted(theSet); if (lastPlane > 0) { if (firstPlane == 0) { firstPlane = 1; firstChar = 0x10000; } numNonBMPPlanes = (lastPlane - firstPlane) + 1; if (isInverted) { numNonBMPPlanes = MAX_ANNEX_PLANE - numNonBMPPlanes; if (firstPlane == lastPlane) { if (((firstChar & 0xFFFF) > 0) || ((lastChar & 0xFFFF) < 0xFFFF)) ++numNonBMPPlanes; } else { if ((firstChar & 0xFFFF) > 0) ++numNonBMPPlanes; if ((lastChar & 0xFFFF) < 0xFFFF) ++numNonBMPPlanes; } } } else if (isInverted) { numNonBMPPlanes = MAX_ANNEX_PLANE; } } else if (isAnnexInverted) { numNonBMPPlanes = MAX_ANNEX_PLANE; } length = __kCFBitmapSize + ((__kCFBitmapSize + 1) * numNonBMPPlanes); data = CFDataCreateMutable(alloc, length); CFDataSetLength(data, length); __CFCSetGetBitmap(theSet, CFDataGetMutableBytePtr(data)); if (numNonBMPPlanes > 0) { char *bytes = CFDataGetMutableBytePtr(data) + __kCFBitmapSize; if (__CFCSetHasNonBMPPlane(theSet)) { CFCharacterSetRef subset; for (idx = 0;idx < numNonBMPPlanes;idx++) { *(bytes++) = planeIndices[idx]; if ((subset = __CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, planeIndices[idx])) == NULL) { __CFCSetBitmapFastFillWithValue((UInt32 *)bytes, (isAnnexInverted ? 0xFF : 0)); } else { __CFCSetGetBitmap(subset, bytes); if (isAnnexInverted) { uint32_t count = __kCFBitmapSize / sizeof(uint32_t); uint32_t *bits = (uint32_t *)bytes; while (count-- > 0) { *bits = ~(*bits); ++bits; } } } bytes += __kCFBitmapSize; } } else if (__CFCSetIsBuiltin(theSet)) { UInt8 result; Boolean isInverted = __CFCSetIsInverted(theSet); for (idx = 0;idx < numNonBMPPlanes;idx++) { if ((result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(theSet), idx + 1, bytes + 1, isInverted)) == kCFUniCharBitmapEmpty) continue; *(bytes++) = idx + 1; if (result == kCFUniCharBitmapAll) { CFIndex bitmapLength = __kCFBitmapSize; while (bitmapLength-- > 0) *(bytes++) = (uint8_t)0xFF; } else { bytes += __kCFBitmapSize; } } if (bytes - (const char *)CFDataGetBytePtr(data) < length) CFDataSetLength(data, bytes - (const char *)CFDataGetBytePtr(data)); } else if (__CFCSetIsRange(theSet)) { UInt32 firstChar = __CFCSetRangeFirstChar(theSet); UInt32 lastChar = __CFCSetRangeFirstChar(theSet) + __CFCSetRangeLength(theSet) - 1; int firstPlane = (firstChar >> 16); int lastPlane = (lastChar >> 16); if (firstPlane == 0) { firstPlane = 1; firstChar = 0x10000; } if (__CFCSetIsInverted(theSet)) { // Mask out the plane byte firstChar &= 0xFFFF; lastChar &= 0xFFFF; for (idx = 1;idx < firstPlane;idx++) { // Fill up until the first plane *(bytes++) = idx; __CFCSetBitmapFastFillWithValue((UInt32 *)bytes, 0xFF); bytes += __kCFBitmapSize; } if (firstPlane == lastPlane) { if ((firstChar > 0) || (lastChar < 0xFFFF)) { *(bytes++) = idx; __CFCSetBitmapFastFillWithValue((UInt32 *)bytes, 0xFF); __CFCSetBitmapRemoveCharactersInRange(bytes, firstChar, lastChar); bytes += __kCFBitmapSize; } } else if (firstPlane < lastPlane) { if (firstChar > 0) { *(bytes++) = idx; __CFCSetBitmapFastFillWithValue((UInt32 *)bytes, 0); __CFCSetBitmapAddCharactersInRange(bytes, 0, firstChar - 1); bytes += __kCFBitmapSize; } if (lastChar < 0xFFFF) { *(bytes++) = idx; __CFCSetBitmapFastFillWithValue((UInt32 *)bytes, 0); __CFCSetBitmapAddCharactersInRange(bytes, lastChar, 0xFFFF); bytes += __kCFBitmapSize; } } for (idx = lastPlane + 1;idx <= MAX_ANNEX_PLANE;idx++) { *(bytes++) = idx; __CFCSetBitmapFastFillWithValue((UInt32 *)bytes, 0xFF); bytes += __kCFBitmapSize; } } else { for (idx = firstPlane;idx <= lastPlane;idx++) { *(bytes++) = idx; __CFCSetBitmapAddCharactersInRange(bytes, (idx == firstPlane ? firstChar : 0), (idx == lastPlane ? lastChar : 0xFFFF)); bytes += __kCFBitmapSize; } } } else if (isAnnexInverted) { for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { *(bytes++) = idx; __CFCSetBitmapFastFillWithValue((UInt32 *)bytes, 0xFF); bytes += __kCFBitmapSize; } } } return data; } /*** MutableCharacterSet functions ***/ void CFCharacterSetAddCharactersInRange(CFMutableCharacterSetRef theSet, CFRange theRange) { CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "addCharactersInRange:", theRange); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); __CFCSetValidateRange(theRange, __PRETTY_FUNCTION__); if (!theRange.length || (__CFCSetIsInverted(theSet) && __CFCSetIsEmpty(theSet))) return; // Inverted && empty set contains all char if (!__CFCSetIsInverted(theSet)) { if (__CFCSetIsEmpty(theSet)) { __CFCSetPutClassType(theSet, __kCFCharSetClassRange); __CFCSetPutRangeFirstChar(theSet, theRange.location); __CFCSetPutRangeLength(theSet, theRange.length); __CFCSetPutHasHashValue(theSet, false); return; } else if (__CFCSetIsRange(theSet)) { CFIndex firstChar = __CFCSetRangeFirstChar(theSet); CFIndex length = __CFCSetRangeLength(theSet); if (firstChar == theRange.location) { __CFCSetPutRangeLength(theSet, __CFMin(length, theRange.length)); __CFCSetPutHasHashValue(theSet, false); return; } else if (firstChar < theRange.location && theRange.location <= firstChar + length) { if (firstChar + length < theRange.location + theRange.length) __CFCSetPutRangeLength(theSet, theRange.length + (theRange.location - firstChar)); __CFCSetPutHasHashValue(theSet, false); return; } else if (theRange.location < firstChar && firstChar <= theRange.location + theRange.length) { __CFCSetPutRangeFirstChar(theSet, theRange.location); __CFCSetPutRangeLength(theSet, length + (firstChar - theRange.location)); __CFCSetPutHasHashValue(theSet, false); return; } } else if (__CFCSetIsString(theSet) && __CFCSetStringLength(theSet) + theRange.length < __kCFStringCharSetMax) { UniChar *buffer; if (!__CFCSetStringBuffer(theSet)) __CFCSetPutStringBuffer(theSet, CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), AUTO_MEMORY_UNSCANNED)); buffer = __CFCSetStringBuffer(theSet) + __CFCSetStringLength(theSet); __CFCSetPutStringLength(theSet, __CFCSetStringLength(theSet) + theRange.length); while (theRange.length--) *buffer++ = theRange.location++; qsort(__CFCSetStringBuffer(theSet), __CFCSetStringLength(theSet), sizeof(UniChar), chcompar); __CFCSetPutHasHashValue(theSet, false); return; } } // OK, I have to be a bitmap __CFCSetMakeBitmap(theSet); __CFCSetAddNonBMPPlanesInRange(theSet, theRange); if (theRange.location < 0x10000) { // theRange is in BMP if (theRange.location + theRange.length >= NUMCHARACTERS) theRange.length = NUMCHARACTERS - theRange.location; __CFCSetBitmapAddCharactersInRange(__CFCSetBitmapBits(theSet), theRange.location, theRange.location + theRange.length - 1); } __CFCSetPutHasHashValue(theSet, false); if (__CFCheckForExapendedSet) __CFCheckForExpandedSet(theSet); } void CFCharacterSetRemoveCharactersInRange(CFMutableCharacterSetRef theSet, CFRange theRange) { CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "removeCharactersInRange:", theRange); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); __CFCSetValidateRange(theRange, __PRETTY_FUNCTION__); if (!theRange.length || (!__CFCSetIsInverted(theSet) && __CFCSetIsEmpty(theSet))) return; // empty set if (__CFCSetIsInverted(theSet)) { if (__CFCSetIsEmpty(theSet)) { __CFCSetPutClassType(theSet, __kCFCharSetClassRange); __CFCSetPutRangeFirstChar(theSet, theRange.location); __CFCSetPutRangeLength(theSet, theRange.length); __CFCSetPutHasHashValue(theSet, false); return; } else if (__CFCSetIsRange(theSet)) { CFIndex firstChar = __CFCSetRangeFirstChar(theSet); CFIndex length = __CFCSetRangeLength(theSet); if (firstChar == theRange.location) { __CFCSetPutRangeLength(theSet, __CFMin(length, theRange.length)); __CFCSetPutHasHashValue(theSet, false); return; } else if (firstChar < theRange.location && theRange.location <= firstChar + length) { if (firstChar + length < theRange.location + theRange.length) __CFCSetPutRangeLength(theSet, theRange.length + (theRange.location - firstChar)); __CFCSetPutHasHashValue(theSet, false); return; } else if (theRange.location < firstChar && firstChar <= theRange.location + theRange.length) { __CFCSetPutRangeFirstChar(theSet, theRange.location); __CFCSetPutRangeLength(theSet, length + (firstChar - theRange.location)); __CFCSetPutHasHashValue(theSet, false); return; } } else if (__CFCSetIsString(theSet) && __CFCSetStringLength(theSet) + theRange.length < __kCFStringCharSetMax) { UniChar *buffer; if (!__CFCSetStringBuffer(theSet)) __CFCSetPutStringBuffer(theSet, CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), AUTO_MEMORY_UNSCANNED)); buffer = __CFCSetStringBuffer(theSet) + __CFCSetStringLength(theSet); __CFCSetPutStringLength(theSet, __CFCSetStringLength(theSet) + theRange.length); while (theRange.length--) *buffer++ = theRange.location++; qsort(__CFCSetStringBuffer(theSet), __CFCSetStringLength(theSet), sizeof(UniChar), chcompar); __CFCSetPutHasHashValue(theSet, false); return; } } // OK, I have to be a bitmap __CFCSetMakeBitmap(theSet); __CFCSetRemoveNonBMPPlanesInRange(theSet, theRange); if (theRange.location < 0x10000) { // theRange is in BMP if (theRange.location + theRange.length > NUMCHARACTERS) theRange.length = NUMCHARACTERS - theRange.location; if (theRange.location == 0 && theRange.length == NUMCHARACTERS) { // Remove all CFAllocatorDeallocate(CFGetAllocator(theSet), __CFCSetBitmapBits(theSet)); __CFCSetPutBitmapBits(theSet, NULL); } else { __CFCSetBitmapRemoveCharactersInRange(__CFCSetBitmapBits(theSet), theRange.location, theRange.location + theRange.length - 1); } } __CFCSetPutHasHashValue(theSet, false); if (__CFCheckForExapendedSet) __CFCheckForExpandedSet(theSet); } void CFCharacterSetAddCharactersInString(CFMutableCharacterSetRef theSet, CFStringRef theString) { const UniChar *buffer; CFIndex length; CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "addCharactersInString:", theString); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); if ((__CFCSetIsEmpty(theSet) && __CFCSetIsInverted(theSet)) || !(length = CFStringGetLength(theString))) return; if (!__CFCSetIsInverted(theSet)) { CFIndex newLength = length + (__CFCSetIsEmpty(theSet) ? 0 : (__CFCSetIsString(theSet) ? __CFCSetStringLength(theSet) : __kCFStringCharSetMax)); if (newLength < __kCFStringCharSetMax) { if (__CFCSetIsEmpty(theSet)) __CFCSetPutStringLength(theSet, 0); // Make sure to reset this if (!__CFCSetStringBuffer(theSet)) __CFCSetPutStringBuffer(theSet, CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), AUTO_MEMORY_UNSCANNED)); buffer = __CFCSetStringBuffer(theSet) + __CFCSetStringLength(theSet); __CFCSetPutClassType(theSet, __kCFCharSetClassString); __CFCSetPutStringLength(theSet, newLength); CFStringGetCharacters(theString, CFRangeMake(0, length), (UniChar*)buffer); qsort(__CFCSetStringBuffer(theSet), newLength, sizeof(UniChar), chcompar); __CFCSetPutHasHashValue(theSet, false); return; } } // OK, I have to be a bitmap __CFCSetMakeBitmap(theSet); if ((buffer = CFStringGetCharactersPtr(theString))) { while (length--) __CFCSetBitmapAddCharacter(__CFCSetBitmapBits(theSet), *buffer++); } else { CFStringInlineBuffer inlineBuffer; CFIndex idx; CFStringInitInlineBuffer(theString, &inlineBuffer, CFRangeMake(0, length)); for (idx = 0;idx < length;idx++) __CFCSetBitmapAddCharacter(__CFCSetBitmapBits(theSet), __CFStringGetCharacterFromInlineBufferQuick(&inlineBuffer, idx)); } __CFCSetPutHasHashValue(theSet, false); if (__CFCheckForExapendedSet) __CFCheckForExpandedSet(theSet); } void CFCharacterSetRemoveCharactersInString(CFMutableCharacterSetRef theSet, CFStringRef theString) { const UniChar *buffer; CFIndex length; CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "removeCharactersInString:", theString); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); if ((__CFCSetIsEmpty(theSet) && !__CFCSetIsInverted(theSet)) || !(length = CFStringGetLength(theString))) return; if (__CFCSetIsInverted(theSet)) { CFIndex newLength = length + (__CFCSetIsEmpty(theSet) ? 0 : (__CFCSetIsString(theSet) ? __CFCSetStringLength(theSet) : __kCFStringCharSetMax)); if (newLength < __kCFStringCharSetMax) { if (__CFCSetIsEmpty(theSet)) __CFCSetPutStringLength(theSet, 0); // Make sure to reset this if (!__CFCSetStringBuffer(theSet)) __CFCSetPutStringBuffer(theSet, CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), AUTO_MEMORY_UNSCANNED)); buffer = __CFCSetStringBuffer(theSet) + __CFCSetStringLength(theSet); __CFCSetPutClassType(theSet, __kCFCharSetClassString); __CFCSetPutStringLength(theSet, newLength); CFStringGetCharacters(theString, CFRangeMake(0, length), (UniChar *)buffer); qsort(__CFCSetStringBuffer(theSet), newLength, sizeof(UniChar), chcompar); __CFCSetPutHasHashValue(theSet, false); return; } } // OK, I have to be a bitmap __CFCSetMakeBitmap(theSet); if ((buffer = CFStringGetCharactersPtr(theString))) { while (length--) __CFCSetBitmapRemoveCharacter(__CFCSetBitmapBits(theSet), *buffer++); } else { CFStringInlineBuffer inlineBuffer; CFIndex idx; CFStringInitInlineBuffer(theString, &inlineBuffer, CFRangeMake(0, length)); for (idx = 0;idx < length;idx++) __CFCSetBitmapRemoveCharacter(__CFCSetBitmapBits(theSet), __CFStringGetCharacterFromInlineBufferQuick(&inlineBuffer, idx)); } __CFCSetPutHasHashValue(theSet, false); if (__CFCheckForExapendedSet) __CFCheckForExpandedSet(theSet); } void CFCharacterSetUnion(CFMutableCharacterSetRef theSet, CFCharacterSetRef theOtherSet) { CFCharacterSetRef expandedSet = NULL; CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "formUnionWithCharacterSet:", theOtherSet); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); if (__CFCSetIsEmpty(theSet) && __CFCSetIsInverted(theSet)) return; // Inverted empty set contains all char if (!CF_IS_OBJC(__kCFCharacterSetTypeID, theOtherSet) || (expandedSet = __CFCharacterSetGetExpandedSetForNSCharacterSet(theOtherSet))) { // Really CF, we can do some trick here if (expandedSet) theOtherSet = expandedSet; if (__CFCSetIsEmpty(theOtherSet)) { if (__CFCSetIsInverted(theOtherSet)) { if (__CFCSetIsString(theSet) && __CFCSetStringBuffer(theSet)) { CFAllocatorDeallocate(CFGetAllocator(theSet), __CFCSetStringBuffer(theSet)); } else if (__CFCSetIsBitmap(theSet) && __CFCSetBitmapBits(theSet)) { CFAllocatorDeallocate(CFGetAllocator(theSet), __CFCSetBitmapBits(theSet)); } else if (__CFCSetIsCompactBitmap(theSet) && __CFCSetCompactBitmapBits(theSet)) { CFAllocatorDeallocate(CFGetAllocator(theSet), __CFCSetCompactBitmapBits(theSet)); } __CFCSetPutClassType(theSet, __kCFCharSetClassRange); __CFCSetPutRangeLength(theSet, 0); __CFCSetPutIsInverted(theSet, true); __CFCSetPutHasHashValue(theSet, false); __CFCSetDeallocateAnnexPlane(theSet); } else { return; // Nothing to do here } } if (__CFCSetIsBuiltin(theOtherSet) && __CFCSetIsEmpty(theSet)) { // theSet can be builtin set __CFCSetPutClassType(theSet, __kCFCharSetClassBuiltin); __CFCSetPutBuiltinType(theSet, __CFCSetBuiltinType(theOtherSet)); __CFCSetPutHasHashValue(theSet, false); } else if (__CFCSetIsRange(theOtherSet)) { if (__CFCSetIsInverted(theOtherSet)) { UTF32Char firstChar = __CFCSetRangeFirstChar(theOtherSet); CFIndex length = __CFCSetRangeLength(theOtherSet); if (firstChar > 0) CFCharacterSetAddCharactersInRange(theSet, CFRangeMake(0, firstChar)); firstChar += length; length = 0x110000 - firstChar; CFCharacterSetAddCharactersInRange(theSet, CFRangeMake(firstChar, length)); } else { CFCharacterSetAddCharactersInRange(theSet, CFRangeMake(__CFCSetRangeFirstChar(theOtherSet), __CFCSetRangeLength(theOtherSet))); } } else if (__CFCSetIsString(theOtherSet)) { CFStringRef string = CFStringCreateWithCharactersNoCopy(CFGetAllocator(theSet), __CFCSetStringBuffer(theOtherSet), __CFCSetStringLength(theOtherSet), kCFAllocatorNull); CFCharacterSetAddCharactersInString(theSet, string); CFRelease(string); } else { __CFCSetMakeBitmap(theSet); if (__CFCSetIsBitmap(theOtherSet)) { UInt32 *bitmap1 = (UInt32*)__CFCSetBitmapBits(theSet); UInt32 *bitmap2 = (UInt32*)__CFCSetBitmapBits(theOtherSet); CFIndex length = __kCFBitmapSize / sizeof(UInt32); while (length--) *bitmap1++ |= *bitmap2++; } else { UInt32 *bitmap1 = (UInt32*)__CFCSetBitmapBits(theSet); UInt32 *bitmap2; CFIndex length = __kCFBitmapSize / sizeof(UInt32); uint8_t bitmapBuffer[__kCFBitmapSize]; __CFCSetGetBitmap(theOtherSet, bitmapBuffer); bitmap2 = (UInt32*)bitmapBuffer; while (length--) *bitmap1++ |= *bitmap2++; } __CFCSetPutHasHashValue(theSet, false); } if (__CFCSetHasNonBMPPlane(theOtherSet)) { CFMutableCharacterSetRef otherSetPlane; int idx; for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((otherSetPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theOtherSet, idx))) { CFCharacterSetUnion((CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx), otherSetPlane); } } } else if (__CFCSetIsBuiltin(theOtherSet)) { CFMutableCharacterSetRef annexPlane; uint8_t bitmapBuffer[__kCFBitmapSize]; uint8_t result; int planeIndex; Boolean isOtherAnnexPlaneInverted = __CFCSetAnnexIsInverted(theOtherSet); UInt32 *bitmap1; UInt32 *bitmap2; CFIndex length; for (planeIndex = 1;planeIndex <= MAX_ANNEX_PLANE;planeIndex++) { result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(theOtherSet), planeIndex, bitmapBuffer, isOtherAnnexPlaneInverted); if (result != kCFUniCharBitmapEmpty) { annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, planeIndex); if (result == kCFUniCharBitmapAll) { CFCharacterSetAddCharactersInRange(annexPlane, CFRangeMake(0x0000, 0x10000)); } else { __CFCSetMakeBitmap(annexPlane); bitmap1 = (UInt32 *)__CFCSetBitmapBits(annexPlane); length = __kCFBitmapSize / sizeof(UInt32); bitmap2 = (UInt32*)bitmapBuffer; while (length--) *bitmap1++ |= *bitmap2++; } } } } if (__CFCheckForExapendedSet) __CFCheckForExpandedSet(theSet); } else { // It's NSCharacterSet CFDataRef bitmapRep = CFCharacterSetCreateBitmapRepresentation(NULL, theOtherSet); const UInt32 *bitmap2 = (bitmapRep && CFDataGetLength(bitmapRep) ? (const UInt32 *)CFDataGetBytePtr(bitmapRep) : NULL); if (bitmap2) { UInt32 *bitmap1; CFIndex length = __kCFBitmapSize / sizeof(UInt32); __CFCSetMakeBitmap(theSet); bitmap1 = (UInt32*)__CFCSetBitmapBits(theSet); while (length--) *bitmap1++ |= *bitmap2++; __CFCSetPutHasHashValue(theSet, false); } CFRelease(bitmapRep); } } void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef theOtherSet) { CFCharacterSetRef expandedSet = NULL; CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "formIntersectionWithCharacterSet:", theOtherSet); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); if (__CFCSetIsEmpty(theSet) && !__CFCSetIsInverted(theSet)) return; // empty set if (!CF_IS_OBJC(__kCFCharacterSetTypeID, theOtherSet) || (expandedSet = __CFCharacterSetGetExpandedSetForNSCharacterSet(theOtherSet))) { // Really CF, we can do some trick here if (expandedSet) theOtherSet = expandedSet; if (__CFCSetIsEmpty(theOtherSet)) { if (!__CFCSetIsInverted(theOtherSet)) { if (__CFCSetIsString(theSet) && __CFCSetStringBuffer(theSet)) { CFAllocatorDeallocate(CFGetAllocator(theSet), __CFCSetStringBuffer(theSet)); } else if (__CFCSetIsBitmap(theSet) && __CFCSetBitmapBits(theSet)) { CFAllocatorDeallocate(CFGetAllocator(theSet), __CFCSetBitmapBits(theSet)); } else if (__CFCSetIsCompactBitmap(theSet) && __CFCSetCompactBitmapBits(theSet)) { CFAllocatorDeallocate(CFGetAllocator(theSet), __CFCSetCompactBitmapBits(theSet)); } __CFCSetPutClassType(theSet, __kCFCharSetClassBitmap); __CFCSetPutBitmapBits(theSet, NULL); __CFCSetPutIsInverted(theSet, false); theSet->_hashValue = 0; __CFCSetPutHasHashValue(theSet, true); __CFCSetDeallocateAnnexPlane(theSet); } } else if (__CFCSetIsEmpty(theSet)) { // non inverted empty set contains all character __CFCSetPutClassType(theSet, __CFCSetClassType(theOtherSet)); __CFCSetPutHasHashValue(theSet, __CFCSetHasHashValue(theOtherSet)); __CFCSetPutIsInverted(theSet, __CFCSetIsInverted(theOtherSet)); theSet->_hashValue = theOtherSet->_hashValue; if (__CFCSetHasNonBMPPlane(theOtherSet)) { CFMutableCharacterSetRef otherSetPlane; int idx; for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((otherSetPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theOtherSet, idx))) { otherSetPlane = (CFMutableCharacterSetRef)CFCharacterSetCreateMutableCopy(CFGetAllocator(theSet), otherSetPlane); __CFCSetPutCharacterSetToAnnexPlane(theSet, otherSetPlane, idx); CFRelease(otherSetPlane); } } __CFCSetAnnexSetIsInverted(theSet, __CFCSetAnnexIsInverted(theOtherSet)); } switch (__CFCSetClassType(theOtherSet)) { case __kCFCharSetClassBuiltin: __CFCSetPutBuiltinType(theSet, __CFCSetBuiltinType(theOtherSet)); break; case __kCFCharSetClassRange: __CFCSetPutRangeFirstChar(theSet, __CFCSetRangeFirstChar(theOtherSet)); __CFCSetPutRangeLength(theSet, __CFCSetRangeLength(theOtherSet)); break; case __kCFCharSetClassString: __CFCSetPutStringLength(theSet, __CFCSetStringLength(theOtherSet)); if (!__CFCSetStringBuffer(theSet)) __CFCSetPutStringBuffer(theSet, CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), AUTO_MEMORY_UNSCANNED)); memmove(__CFCSetStringBuffer(theSet), __CFCSetStringBuffer(theOtherSet), __CFCSetStringLength(theSet) * sizeof(UniChar)); break; case __kCFCharSetClassBitmap: __CFCSetPutBitmapBits(theSet, CFAllocatorAllocate(CFGetAllocator(theSet), sizeof(uint8_t) * __kCFBitmapSize, AUTO_MEMORY_UNSCANNED)); memmove(__CFCSetBitmapBits(theSet), __CFCSetBitmapBits(theOtherSet), __kCFBitmapSize); break; case __kCFCharSetClassCompactBitmap: { const uint8_t *cBitmap = __CFCSetCompactBitmapBits(theOtherSet); uint8_t *newBitmap; uint32_t size = __CFCSetGetCompactBitmapSize(cBitmap); newBitmap = (uint8_t *)CFAllocatorAllocate(CFGetAllocator(theSet), sizeof(uint8_t) * size, AUTO_MEMORY_UNSCANNED); __CFCSetPutBitmapBits(theSet, newBitmap); memmove(newBitmap, cBitmap, size); } break; default: CFAssert1(0, __kCFLogAssertion, "%s: Internal inconsistency error: unknown character set type", __PRETTY_FUNCTION__); // We should never come here } } else { __CFCSetMakeBitmap(theSet); if (__CFCSetIsBitmap(theOtherSet)) { UInt32 *bitmap1 = (UInt32*)__CFCSetBitmapBits(theSet); UInt32 *bitmap2 = (UInt32*)__CFCSetBitmapBits(theOtherSet); CFIndex length = __kCFBitmapSize / sizeof(UInt32); while (length--) *bitmap1++ &= *bitmap2++; } else { UInt32 *bitmap1 = (UInt32*)__CFCSetBitmapBits(theSet); UInt32 *bitmap2; CFIndex length = __kCFBitmapSize / sizeof(UInt32); uint8_t bitmapBuffer[__kCFBitmapSize]; __CFCSetGetBitmap(theOtherSet, bitmapBuffer); bitmap2 = (UInt32*)bitmapBuffer; while (length--) *bitmap1++ &= *bitmap2++; } __CFCSetPutHasHashValue(theSet, false); if (__CFCSetHasNonBMPPlane(theOtherSet)) { CFMutableCharacterSetRef annexPlane; CFMutableCharacterSetRef otherSetPlane; int idx; for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((otherSetPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theOtherSet, idx))) { annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx); CFCharacterSetIntersect(annexPlane, otherSetPlane); if (__CFCSetIsEmpty(annexPlane) && !__CFCSetIsInverted(annexPlane)) __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); } else if (__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) { __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); } } if (!__CFCSetHasNonBMPPlane(theSet)) __CFCSetDeallocateAnnexPlane(theSet); } else if (__CFCSetIsBuiltin(theOtherSet)) { CFMutableCharacterSetRef annexPlane; uint8_t bitmapBuffer[__kCFBitmapSize]; uint8_t result; int planeIndex; Boolean isOtherAnnexPlaneInverted = __CFCSetAnnexIsInverted(theOtherSet); UInt32 *bitmap1; UInt32 *bitmap2; CFIndex length; for (planeIndex = 1;planeIndex <= MAX_ANNEX_PLANE;planeIndex++) { annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, planeIndex); if (annexPlane) { result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(theOtherSet), planeIndex, bitmapBuffer, isOtherAnnexPlaneInverted); if (result == kCFUniCharBitmapEmpty) { __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, planeIndex); } else if (result == kCFUniCharBitmapFilled) { Boolean isEmpty = true; __CFCSetMakeBitmap(annexPlane); bitmap1 = (UInt32 *)__CFCSetBitmapBits(annexPlane); length = __kCFBitmapSize / sizeof(UInt32); bitmap2 = (UInt32*)bitmapBuffer; while (length--) { if ((*bitmap1++ &= *bitmap2++)) isEmpty = false; } if (isEmpty) __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, planeIndex); } } } if (!__CFCSetHasNonBMPPlane(theSet)) __CFCSetDeallocateAnnexPlane(theSet); } else if (__CFCSetIsRange(theOtherSet)) { CFMutableCharacterSetRef tempOtherSet = CFCharacterSetCreateMutable(CFGetAllocator(theSet)); CFMutableCharacterSetRef annexPlane; CFMutableCharacterSetRef otherSetPlane; int idx; __CFCSetAddNonBMPPlanesInRange(tempOtherSet, CFRangeMake(__CFCSetRangeFirstChar(theOtherSet), __CFCSetRangeLength(theOtherSet))); for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((otherSetPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(tempOtherSet, idx))) { annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx); CFCharacterSetIntersect(annexPlane, otherSetPlane); if (__CFCSetIsEmpty(annexPlane) && !__CFCSetIsInverted(annexPlane)) __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); } else if (__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) { __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); } } if (!__CFCSetHasNonBMPPlane(theSet)) __CFCSetDeallocateAnnexPlane(theSet); CFRelease(tempOtherSet); } else if (__CFCSetHasNonBMPPlane(theSet)) { __CFCSetDeallocateAnnexPlane(theSet); } } if (__CFCheckForExapendedSet) __CFCheckForExpandedSet(theSet); } else { // It's NSCharacterSet CFDataRef bitmapRep = CFCharacterSetCreateBitmapRepresentation(NULL, theOtherSet); const UInt32 *bitmap2 = (bitmapRep && CFDataGetLength(bitmapRep) ? (const UInt32 *)CFDataGetBytePtr(bitmapRep) : NULL); if (bitmap2) { UInt32 *bitmap1; CFIndex length = __kCFBitmapSize / sizeof(UInt32); __CFCSetMakeBitmap(theSet); bitmap1 = (UInt32*)__CFCSetBitmapBits(theSet); while (length--) *bitmap1++ &= *bitmap2++; __CFCSetPutHasHashValue(theSet, false); } CFRelease(bitmapRep); } } void CFCharacterSetInvert(CFMutableCharacterSetRef theSet) { CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, void, theSet, "invert"); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); __CFCSetPutHasHashValue(theSet, false); if (__CFCSetClassType(theSet) == __kCFCharSetClassBitmap) { CFIndex idx; CFIndex count = __kCFBitmapSize / sizeof(UInt32); UInt32 *bitmap = (UInt32*) __CFCSetBitmapBits(theSet); if (NULL == bitmap) { bitmap = (UInt32 *)CFAllocatorAllocate(CFGetAllocator(theSet), __kCFBitmapSize, AUTO_MEMORY_UNSCANNED); __CFCSetPutBitmapBits(theSet, (uint8_t *)bitmap); for (idx = 0;idx < count;idx++) bitmap[idx] = 0xFFFFFFFF; } else { for (idx = 0;idx < count;idx++) bitmap[idx] = ~(bitmap[idx]); } __CFCSetAllocateAnnexForPlane(theSet, 0); // We need to alloc annex to invert } else if (__CFCSetClassType(theSet) == __kCFCharSetClassCompactBitmap) { uint8_t *bitmap = __CFCSetCompactBitmapBits(theSet); int idx; int length = 0; uint8_t value; for (idx = 0;idx < __kCFCompactBitmapNumPages;idx++) { value = bitmap[idx]; if (value == 0) { bitmap[idx] = UINT8_MAX; } else if (value == UINT8_MAX) { bitmap[idx] = 0; } else { length += __kCFCompactBitmapPageSize; } } bitmap += __kCFCompactBitmapNumPages; for (idx = 0;idx < length;idx++) bitmap[idx] = ~(bitmap[idx]); __CFCSetAllocateAnnexForPlane(theSet, 0); // We need to alloc annex to invert } else { __CFCSetPutIsInverted(theSet, !__CFCSetIsInverted(theSet)); } __CFCSetAnnexSetIsInverted(theSet, !__CFCSetAnnexIsInverted(theSet)); } void CFCharacterSetCompact(CFMutableCharacterSetRef theSet) { if (__CFCSetIsBitmap(theSet) && __CFCSetBitmapBits(theSet)) __CFCSetMakeCompact(theSet); if (__CFCSetHasNonBMPPlane(theSet)) { CFMutableCharacterSetRef annex; int idx; for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((annex = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) && __CFCSetIsBitmap(annex) && __CFCSetBitmapBits(annex)) { __CFCSetMakeCompact(annex); } } } } void CFCharacterSetFast(CFMutableCharacterSetRef theSet) { if (__CFCSetIsCompactBitmap(theSet) && __CFCSetCompactBitmapBits(theSet)) __CFCSetMakeBitmap(theSet); if (__CFCSetHasNonBMPPlane(theSet)) { CFMutableCharacterSetRef annex; int idx; for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((annex = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) && __CFCSetIsCompactBitmap(annex) && __CFCSetCompactBitmapBits(annex)) { __CFCSetMakeBitmap(annex); } } } } /* Keyed-coding support */ CFCharacterSetKeyedCodingType _CFCharacterSetGetKeyedCodingType(CFCharacterSetRef cset) { switch (__CFCSetClassType(cset)) { case __kCFCharSetClassBuiltin: return ((__CFCSetBuiltinType(cset) < kCFCharacterSetSymbol) ? kCFCharacterSetKeyedCodingTypeBuiltin : kCFCharacterSetKeyedCodingTypeBitmap); case __kCFCharSetClassRange: return kCFCharacterSetKeyedCodingTypeRange; case __kCFCharSetClassString: // We have to check if we have non-BMP here if (!__CFCSetHasNonBMPPlane(cset)) return kCFCharacterSetKeyedCodingTypeString; // BMP only. we can archive the string /* fallthrough */ default: return kCFCharacterSetKeyedCodingTypeBitmap; } } CFCharacterSetPredefinedSet _CFCharacterSetGetKeyedCodingBuiltinType(CFCharacterSetRef cset) { return __CFCSetBuiltinType(cset); } CFRange _CFCharacterSetGetKeyedCodingRange(CFCharacterSetRef cset) { return CFRangeMake(__CFCSetRangeFirstChar(cset), __CFCSetRangeLength(cset)); } CFStringRef _CFCharacterSetCreateKeyedCodingString(CFCharacterSetRef cset) { return CFStringCreateWithCharacters(NULL, __CFCSetStringBuffer(cset), __CFCSetStringLength(cset)); } bool _CFCharacterSetIsInverted(CFCharacterSetRef cset) { return __CFCSetIsInverted(cset); } void _CFCharacterSetSetIsInverted(CFCharacterSetRef cset, bool flag) { __CFCSetPutIsInverted((CFMutableCharacterSetRef)cset, flag); }