#import "NSDictionary+CaseInsensitive.h" #include #define PSPDF_ALLOW_CAST_QUALIFIERS(expression) _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wcast-qual\"") expression _Pragma("clang diagnostic pop") @implementation NSDictionary (PSPDFFoundation) static Boolean PSPDFCaseInsensitiveEqualCallback(const void *a, const void *b) { id objA = (__bridge id)a, objB = (__bridge id)b; Boolean ret = FALSE; if ([objA isKindOfClass:NSString.class] && [objB isKindOfClass:NSString.class]) { ret = ([objA compare:objB options:NSCaseInsensitiveSearch | NSLiteralSearch] == NSOrderedSame); } else { ret = (Boolean)[objA isEqual:objB]; } return ret; } static CFHashCode PSPDFCaseInsensitiveHashCallback(const void *value) { id obj = (__bridge id)value; NSObject *objToHash = PSPDFCast(obj, NSString).lowercaseString ?: obj; return objToHash.hash; } - (NSDictionary *)pst_caseInsensitiveDictionary { std::vector keys, values; let count = CFDictionaryGetCount((CFDictionaryRef)self); if (count) { keys.reserve(count); values.reserve(count); PSPDF_ALLOW_CAST_QUALIFIERS(CFDictionaryGetKeysAndValues((CFDictionaryRef)self, (const void **)keys.data(), (const void **)values.data());) } CFDictionaryKeyCallBacks keyCallbacks = kCFCopyStringDictionaryKeyCallBacks; keyCallbacks.equal = PSPDFCaseInsensitiveEqualCallback; keyCallbacks.hash = PSPDFCaseInsensitiveHashCallback; PSPDF_ALLOW_CAST_QUALIFIERS(CFDictionaryRef caseInsensitiveDict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys.data(), (const void **)values.data(), count, &keyCallbacks, &kCFTypeDictionaryValueCallBacks);) return (NSDictionary *)CFBridgingRelease(caseInsensitiveDict); } @end