| /* CFPlugIn.c |
| Copyright (c) 1999-2017, Apple Inc. and the Swift project authors |
| |
| Portions Copyright (c) 2014-2017, Apple Inc. and the Swift project authors |
| Licensed under Apache License v2.0 with Runtime Library Exception |
| See http://swift.org/LICENSE.txt for license information |
| See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| Responsibility: Tony Parker |
| */ |
| |
| #include "CFBundle_Internal.h" |
| #include "CFInternal.h" |
| |
| CONST_STRING_DECL(kCFPlugInDynamicRegistrationKey, "CFPlugInDynamicRegistration") |
| CONST_STRING_DECL(kCFPlugInDynamicRegisterFunctionKey, "CFPlugInDynamicRegisterFunction") |
| CONST_STRING_DECL(kCFPlugInUnloadFunctionKey, "CFPlugInUnloadFunction") |
| CONST_STRING_DECL(kCFPlugInFactoriesKey, "CFPlugInFactories") |
| CONST_STRING_DECL(kCFPlugInTypesKey, "CFPlugInTypes") |
| |
| CF_PRIVATE void __CFPlugInInitialize(void) { |
| } |
| |
| /* ===================== Finding factories and creating instances ===================== */ |
| /* For plugIn hosts. */ |
| /* Functions for finding factories to create specific types and actually creating instances of a type. */ |
| |
| CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInType(CFUUIDRef typeID) { |
| CFArrayRef array = _CFPFactoryFindCopyForType(typeID); |
| CFMutableArrayRef result = NULL; |
| |
| if (array) { |
| SInt32 i, c = CFArrayGetCount(array); |
| result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); |
| for (i = 0; i < c; i++) { |
| CFUUIDRef factoryId = _CFPFactoryCopyFactoryID((_CFPFactoryRef)CFArrayGetValueAtIndex(array, i)); |
| if (factoryId) { |
| CFArrayAppendValue(result, factoryId); |
| CFRelease(factoryId); |
| } |
| } |
| CFRelease(array); |
| } |
| return result; |
| } |
| |
| CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInTypeInPlugIn(CFUUIDRef typeID, CFPlugInRef plugIn) { |
| CFArrayRef array = _CFPFactoryFindCopyForType(typeID); |
| CFMutableArrayRef result = NULL; |
| |
| if (array) { |
| SInt32 i, c = CFArrayGetCount(array); |
| _CFPFactoryRef factory; |
| result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); |
| for (i = 0; i < c; i++) { |
| factory = (_CFPFactoryRef )CFArrayGetValueAtIndex(array, i); |
| CFPlugInRef factoryPlugIn = _CFPFactoryCopyPlugIn(factory); |
| if (factoryPlugIn == plugIn) { |
| CFUUIDRef factoryId = _CFPFactoryCopyFactoryID(factory); |
| CFArrayAppendValue(result, factoryId); |
| CFRelease(factoryId); |
| } |
| if (factoryPlugIn) CFRelease(factoryPlugIn); |
| } |
| CFRelease(array); |
| } |
| return result; |
| } |
| |
| CF_EXPORT void *CFPlugInInstanceCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFUUIDRef typeID) { |
| _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true); |
| void *result = NULL; |
| if (!factory) { |
| /* MF:!!! No such factory. */ |
| CFLog(__kCFLogPlugIn, CFSTR("Cannot find factory %@"), factoryID); |
| } else { |
| if (!_CFPFactorySupportsType(factory, typeID)) { |
| /* MF:!!! Factory does not support type. */ |
| CFLog(__kCFLogPlugIn, CFSTR("Factory %@ does not support type %@"), factoryID, typeID); |
| } else { |
| result = _CFPFactoryCreateInstance(allocator, factory, typeID); |
| } |
| } |
| return result; |
| } |
| |
| /* ===================== Registering factories and types ===================== */ |
| /* For plugIn writers who must dynamically register things. */ |
| /* Functions to register factory functions and to associate factories with types. */ |
| |
| CF_EXPORT Boolean CFPlugInRegisterFactoryFunction(CFUUIDRef factoryID, CFPlugInFactoryFunction func) { |
| // Create factories without plugIns from default allocator |
| // MF:!!! Should probably check that this worked, and maybe do some pre-checking to see if it already exists |
| // _CFPFactoryRef factory = |
| (void)_CFPFactoryCreate(kCFAllocatorSystemDefault, factoryID, func); |
| return true; |
| } |
| |
| CF_EXPORT Boolean CFPlugInRegisterFactoryFunctionByName(CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef functionName) { |
| // Create factories with plugIns from plugIn's allocator |
| // MF:!!! Should probably check that this worked, and maybe do some pre-checking to see if it already exists |
| // _CFPFactoryRef factory = |
| (void)_CFPFactoryCreateByName(CFGetAllocator(plugIn), factoryID, plugIn, functionName); |
| return true; |
| } |
| |
| CF_EXPORT Boolean CFPlugInUnregisterFactory(CFUUIDRef factoryID) { |
| _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true); |
| |
| if (!factory) { |
| /* MF:!!! Error. No factory registered for this ID. */ |
| } else { |
| _CFPFactoryDisable(factory); |
| } |
| return true; |
| } |
| |
| CF_EXPORT Boolean CFPlugInRegisterPlugInType(CFUUIDRef factoryID, CFUUIDRef typeID) { |
| _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true); |
| |
| if (!factory) { |
| /* MF:!!! Error. Factory must be registered (and not disabled) before types can be associated with it. */ |
| } else { |
| _CFPFactoryAddType(factory, typeID); |
| } |
| return true; |
| } |
| |
| CF_EXPORT Boolean CFPlugInUnregisterPlugInType(CFUUIDRef factoryID, CFUUIDRef typeID) { |
| _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true); |
| |
| if (!factory) { |
| /* MF:!!! Error. Could not find factory. */ |
| } else { |
| _CFPFactoryRemoveType(factory, typeID); |
| } |
| return true; |
| } |
| |
| |
| /* ================= Registering instances ================= */ |
| /* When a new instance of a type is created, the instance is responsible for registering itself with the factory that created it and unregistering when it deallocates. */ |
| /* This means that an instance must keep track of the CFUUIDRef of the factory that created it so it can unregister when it goes away. */ |
| |
| CF_EXPORT void CFPlugInAddInstanceForFactory(CFUUIDRef factoryID) { |
| _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true); |
| |
| if (!factory) { |
| /* MF:!!! Error. Could not find factory. */ |
| } else { |
| _CFPFactoryAddInstance(factory); |
| } |
| } |
| |
| CF_EXPORT void CFPlugInRemoveInstanceForFactory(CFUUIDRef factoryID) { |
| _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true); |
| |
| if (!factory) { |
| /* MF:!!! Error. Could not find factory. */ |
| } else { |
| _CFPFactoryRemoveInstance(factory); |
| } |
| } |