]> git.saurik.com Git - apple/cf.git/blame - CFPlugIn_Factory.c
CF-635.15.tar.gz
[apple/cf.git] / CFPlugIn_Factory.c
CommitLineData
9ce05555 1/*
8ca704e1 2 * Copyright (c) 2011 Apple Inc. All rights reserved.
9ce05555
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
9ce05555
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
f64f9b69 23
9ce05555 24/* CFPlugIn_Factory.c
8ca704e1
A
25 Copyright (c) 1999-2011, Apple Inc. All rights reserved.
26 Responsibility: David Smith
9ce05555
A
27*/
28
29#include "CFBundle_Internal.h"
30#include "CFInternal.h"
31
bd5b749c 32static CFSpinLock_t CFPlugInGlobalDataLock = CFSpinLockInit;
9ce05555
A
33static CFMutableDictionaryRef _factoriesByFactoryID = NULL; /* Value is _CFPFactory */
34static CFMutableDictionaryRef _factoriesByTypeID = NULL; /* Value is array of _CFPFactory */
35
36static void _CFPFactoryAddToTable(_CFPFactory *factory) {
37 __CFSpinLock(&CFPlugInGlobalDataLock);
cf7d2af9 38 if (!_factoriesByFactoryID) {
9ce05555 39 CFDictionaryValueCallBacks _factoryDictValueCallbacks = {0, NULL, NULL, NULL, NULL};
bd5b749c 40 _factoriesByFactoryID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &_factoryDictValueCallbacks);
9ce05555
A
41 }
42 CFDictionarySetValue(_factoriesByFactoryID, factory->_uuid, factory);
43 __CFSpinUnlock(&CFPlugInGlobalDataLock);
44}
45
46static void _CFPFactoryRemoveFromTable(_CFPFactory *factory) {
47 __CFSpinLock(&CFPlugInGlobalDataLock);
cf7d2af9 48 if (_factoriesByFactoryID) CFDictionaryRemoveValue(_factoriesByFactoryID, factory->_uuid);
9ce05555
A
49 __CFSpinUnlock(&CFPlugInGlobalDataLock);
50}
51
52__private_extern__ _CFPFactory *_CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled) {
53 _CFPFactory *result = NULL;
54
55 __CFSpinLock(&CFPlugInGlobalDataLock);
cf7d2af9 56 if (_factoriesByFactoryID) {
9ce05555 57 result = (_CFPFactory *)CFDictionaryGetValue(_factoriesByFactoryID, factoryID);
cf7d2af9 58 if (result && result->_enabled != enabled) result = NULL;
9ce05555
A
59 }
60 __CFSpinUnlock(&CFPlugInGlobalDataLock);
61 return result;
62}
63
64static void _CFPFactoryDeallocate(_CFPFactory *factory) {
65 CFAllocatorRef allocator = factory->_allocator;
66 SInt32 c;
67
68 _CFPFactoryRemoveFromTable(factory);
69
cf7d2af9 70 if (factory->_plugIn) _CFPlugInRemoveFactory(factory->_plugIn, factory);
9ce05555
A
71
72 /* Remove all types for this factory. */
73 c = CFArrayGetCount(factory->_types);
cf7d2af9 74 while (c-- > 0) _CFPFactoryRemoveType(factory, (CFUUIDRef)CFArrayGetValueAtIndex(factory->_types, c));
9ce05555
A
75 CFRelease(factory->_types);
76
cf7d2af9
A
77 if (factory->_funcName) CFRelease(factory->_funcName);
78 if (factory->_uuid) CFRelease(factory->_uuid);
9ce05555
A
79
80 CFAllocatorDeallocate(allocator, factory);
81 CFRelease(allocator);
82}
83
84static _CFPFactory *_CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRef factoryID) {
85 _CFPFactory *factory;
86 UInt32 size;
87 size = sizeof(_CFPFactory);
cf7d2af9 88 allocator = (allocator ? (CFAllocatorRef)CFRetain(allocator) : (CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()));
bd5b749c 89 factory = (_CFPFactory *)CFAllocatorAllocate(allocator, size, 0);
cf7d2af9 90 if (!factory) {
9ce05555
A
91 CFRelease(allocator);
92 return NULL;
93 }
94
95 factory->_allocator = allocator;
bd5b749c 96 factory->_uuid = (CFUUIDRef)CFRetain(factoryID);
9ce05555
A
97 factory->_enabled = true;
98 factory->_instanceCount = 0;
99
100 _CFPFactoryAddToTable(factory);
101
102 factory->_types = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
103
104 return factory;
105}
106
107__private_extern__ _CFPFactory *_CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func) {
108 _CFPFactory *factory = _CFPFactoryCommonCreate(allocator, factoryID);
109
110 factory->_func = func;
111 factory->_plugIn = NULL;
112 factory->_funcName = NULL;
113
114 return factory;
115}
116
117__private_extern__ _CFPFactory *_CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName) {
118 _CFPFactory *factory = _CFPFactoryCommonCreate(allocator, factoryID);
119
120 factory->_func = NULL;
121 factory->_plugIn = plugIn;
cf7d2af9 122 if (plugIn) _CFPlugInAddFactory(plugIn, factory);
bd5b749c 123 factory->_funcName = (funcName ? (CFStringRef)CFStringCreateCopy(allocator, funcName) : NULL);
9ce05555
A
124
125 return factory;
126}
127
128__private_extern__ CFUUIDRef _CFPFactoryGetFactoryID(_CFPFactory *factory) {
129 return factory->_uuid;
130}
131
132__private_extern__ CFPlugInRef _CFPFactoryGetPlugIn(_CFPFactory *factory) {
133 return factory->_plugIn;
134}
135
136__private_extern__ void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactory *factory, CFUUIDRef typeID) {
137 void *result = NULL;
138 if (factory->_enabled) {
cf7d2af9 139 if (!factory->_func) {
bd5b749c 140 factory->_func = (CFPlugInFactoryFunction)CFBundleGetFunctionPointerForName(factory->_plugIn, factory->_funcName);
cf7d2af9 141 if (!factory->_func) CFLog(__kCFLogPlugIn, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory->_funcName, factory->_uuid, factory->_plugIn);
9ce05555
A
142 }
143 if (factory->_func) {
9ce05555
A
144 // UPPGOOP
145 FAULT_CALLBACK((void **)&(factory->_func));
146 result = (void *)INVOKE_CALLBACK2(factory->_func, allocator, typeID);
9ce05555
A
147 }
148 } else {
149 CFLog(__kCFLogPlugIn, CFSTR("Factory %@ is disabled"), factory->_uuid);
150 }
151 return result;
152}
153
154__private_extern__ void _CFPFactoryDisable(_CFPFactory *factory) {
155 factory->_enabled = false;
cf7d2af9 156 if (factory->_instanceCount == 0) _CFPFactoryDeallocate(factory);
9ce05555
A
157}
158
159__private_extern__ Boolean _CFPFactoryIsEnabled(_CFPFactory *factory) {
160 return factory->_enabled;
161}
162
163__private_extern__ void _CFPFactoryFlushFunctionCache(_CFPFactory *factory) {
164 /* MF:!!! Assert that this factory belongs to a plugIn. */
165 /* This is called by the factory's plugIn when the plugIn unloads its code. */
166 factory->_func = NULL;
167}
168
169__private_extern__ void _CFPFactoryAddType(_CFPFactory *factory, CFUUIDRef typeID) {
170 CFMutableArrayRef array;
171
172 /* Add the type to the factory's type list */
173 CFArrayAppendValue(factory->_types, typeID);
174
175 /* Add the factory to the type's array of factories */
176 __CFSpinLock(&CFPlugInGlobalDataLock);
cf7d2af9 177 if (!_factoriesByTypeID) _factoriesByTypeID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
9ce05555 178 array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
cf7d2af9 179 if (!array) {
9ce05555
A
180 CFArrayCallBacks _factoryArrayCallbacks = {0, NULL, NULL, NULL, NULL};
181 // Create this from default allocator
bd5b749c 182 array = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &_factoryArrayCallbacks);
9ce05555
A
183 CFDictionarySetValue(_factoriesByTypeID, typeID, array);
184 CFRelease(array);
185 }
186 CFArrayAppendValue(array, factory);
187 __CFSpinUnlock(&CFPlugInGlobalDataLock);
188}
189
190__private_extern__ void _CFPFactoryRemoveType(_CFPFactory *factory, CFUUIDRef typeID) {
191 /* Remove it from the factory's type list */
192 SInt32 idx;
193
194 idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID);
cf7d2af9 195 if (idx >= 0) CFArrayRemoveValueAtIndex(factory->_types, idx);
9ce05555
A
196
197 /* Remove the factory from the type's list of factories */
198 __CFSpinLock(&CFPlugInGlobalDataLock);
cf7d2af9 199 if (_factoriesByTypeID) {
9ce05555 200 CFMutableArrayRef array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
cf7d2af9 201 if (array) {
9ce05555 202 idx = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), factory);
cf7d2af9 203 if (idx >= 0) {
9ce05555 204 CFArrayRemoveValueAtIndex(array, idx);
cf7d2af9 205 if (CFArrayGetCount(array) == 0) CFDictionaryRemoveValue(_factoriesByTypeID, typeID);
9ce05555
A
206 }
207 }
208 }
209 __CFSpinUnlock(&CFPlugInGlobalDataLock);
210}
211
212__private_extern__ Boolean _CFPFactorySupportsType(_CFPFactory *factory, CFUUIDRef typeID) {
213 SInt32 idx;
214
215 idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID);
cf7d2af9 216 return (idx >= 0 ? true : false);
9ce05555
A
217}
218
219__private_extern__ CFArrayRef _CFPFactoryFindForType(CFUUIDRef typeID) {
220 CFArrayRef result = NULL;
221
222 __CFSpinLock(&CFPlugInGlobalDataLock);
cf7d2af9 223 if (_factoriesByTypeID) result = (CFArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
9ce05555
A
224 __CFSpinUnlock(&CFPlugInGlobalDataLock);
225
226 return result;
227}
228
229/* These methods are called by CFPlugInInstance when an instance is created or destroyed. If a factory's instance count goes to 0 and the factory has been disabled, the factory is destroyed. */
230__private_extern__ void _CFPFactoryAddInstance(_CFPFactory *factory) {
231 /* MF:!!! Assert that factory is enabled. */
232 factory->_instanceCount++;
cf7d2af9 233 if (factory->_plugIn) _CFPlugInAddPlugInInstance(factory->_plugIn);
9ce05555
A
234}
235
236__private_extern__ void _CFPFactoryRemoveInstance(_CFPFactory *factory) {
237 /* MF:!!! Assert that _instanceCount > 0. */
238 factory->_instanceCount--;
cf7d2af9
A
239 if (factory->_plugIn) _CFPlugInRemovePlugInInstance(factory->_plugIn);
240 if (factory->_instanceCount == 0 && !factory->_enabled) _CFPFactoryDeallocate(factory);
9ce05555 241}