]> git.saurik.com Git - apple/cf.git/blob - CFPlugIn_Factory.c
CF-635.21.tar.gz
[apple/cf.git] / CFPlugIn_Factory.c
1 /*
2 * Copyright (c) 2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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 */
23
24 /* CFPlugIn_Factory.c
25 Copyright (c) 1999-2011, Apple Inc. All rights reserved.
26 Responsibility: David Smith
27 */
28
29 #include "CFBundle_Internal.h"
30 #include "CFInternal.h"
31
32 static CFSpinLock_t CFPlugInGlobalDataLock = CFSpinLockInit;
33 static CFMutableDictionaryRef _factoriesByFactoryID = NULL; /* Value is _CFPFactory */
34 static CFMutableDictionaryRef _factoriesByTypeID = NULL; /* Value is array of _CFPFactory */
35
36 static void _CFPFactoryAddToTable(_CFPFactory *factory) {
37 __CFSpinLock(&CFPlugInGlobalDataLock);
38 if (!_factoriesByFactoryID) {
39 CFDictionaryValueCallBacks _factoryDictValueCallbacks = {0, NULL, NULL, NULL, NULL};
40 _factoriesByFactoryID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &_factoryDictValueCallbacks);
41 }
42 CFDictionarySetValue(_factoriesByFactoryID, factory->_uuid, factory);
43 __CFSpinUnlock(&CFPlugInGlobalDataLock);
44 }
45
46 static void _CFPFactoryRemoveFromTable(_CFPFactory *factory) {
47 __CFSpinLock(&CFPlugInGlobalDataLock);
48 if (_factoriesByFactoryID) CFDictionaryRemoveValue(_factoriesByFactoryID, factory->_uuid);
49 __CFSpinUnlock(&CFPlugInGlobalDataLock);
50 }
51
52 __private_extern__ _CFPFactory *_CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled) {
53 _CFPFactory *result = NULL;
54
55 __CFSpinLock(&CFPlugInGlobalDataLock);
56 if (_factoriesByFactoryID) {
57 result = (_CFPFactory *)CFDictionaryGetValue(_factoriesByFactoryID, factoryID);
58 if (result && result->_enabled != enabled) result = NULL;
59 }
60 __CFSpinUnlock(&CFPlugInGlobalDataLock);
61 return result;
62 }
63
64 static void _CFPFactoryDeallocate(_CFPFactory *factory) {
65 CFAllocatorRef allocator = factory->_allocator;
66 SInt32 c;
67
68 _CFPFactoryRemoveFromTable(factory);
69
70 if (factory->_plugIn) _CFPlugInRemoveFactory(factory->_plugIn, factory);
71
72 /* Remove all types for this factory. */
73 c = CFArrayGetCount(factory->_types);
74 while (c-- > 0) _CFPFactoryRemoveType(factory, (CFUUIDRef)CFArrayGetValueAtIndex(factory->_types, c));
75 CFRelease(factory->_types);
76
77 if (factory->_funcName) CFRelease(factory->_funcName);
78 if (factory->_uuid) CFRelease(factory->_uuid);
79
80 CFAllocatorDeallocate(allocator, factory);
81 CFRelease(allocator);
82 }
83
84 static _CFPFactory *_CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRef factoryID) {
85 _CFPFactory *factory;
86 UInt32 size;
87 size = sizeof(_CFPFactory);
88 allocator = (allocator ? (CFAllocatorRef)CFRetain(allocator) : (CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()));
89 factory = (_CFPFactory *)CFAllocatorAllocate(allocator, size, 0);
90 if (!factory) {
91 CFRelease(allocator);
92 return NULL;
93 }
94
95 factory->_allocator = allocator;
96 factory->_uuid = (CFUUIDRef)CFRetain(factoryID);
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;
122 if (plugIn) _CFPlugInAddFactory(plugIn, factory);
123 factory->_funcName = (funcName ? (CFStringRef)CFStringCreateCopy(allocator, funcName) : NULL);
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) {
139 if (!factory->_func) {
140 factory->_func = (CFPlugInFactoryFunction)CFBundleGetFunctionPointerForName(factory->_plugIn, factory->_funcName);
141 if (!factory->_func) CFLog(__kCFLogPlugIn, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory->_funcName, factory->_uuid, factory->_plugIn);
142 }
143 if (factory->_func) {
144 // UPPGOOP
145 FAULT_CALLBACK((void **)&(factory->_func));
146 result = (void *)INVOKE_CALLBACK2(factory->_func, allocator, typeID);
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;
156 if (factory->_instanceCount == 0) _CFPFactoryDeallocate(factory);
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);
177 if (!_factoriesByTypeID) _factoriesByTypeID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
178 array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
179 if (!array) {
180 CFArrayCallBacks _factoryArrayCallbacks = {0, NULL, NULL, NULL, NULL};
181 // Create this from default allocator
182 array = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &_factoryArrayCallbacks);
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);
195 if (idx >= 0) CFArrayRemoveValueAtIndex(factory->_types, idx);
196
197 /* Remove the factory from the type's list of factories */
198 __CFSpinLock(&CFPlugInGlobalDataLock);
199 if (_factoriesByTypeID) {
200 CFMutableArrayRef array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
201 if (array) {
202 idx = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), factory);
203 if (idx >= 0) {
204 CFArrayRemoveValueAtIndex(array, idx);
205 if (CFArrayGetCount(array) == 0) CFDictionaryRemoveValue(_factoriesByTypeID, typeID);
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);
216 return (idx >= 0 ? true : false);
217 }
218
219 __private_extern__ CFArrayRef _CFPFactoryFindForType(CFUUIDRef typeID) {
220 CFArrayRef result = NULL;
221
222 __CFSpinLock(&CFPlugInGlobalDataLock);
223 if (_factoriesByTypeID) result = (CFArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
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++;
233 if (factory->_plugIn) _CFPlugInAddPlugInInstance(factory->_plugIn);
234 }
235
236 __private_extern__ void _CFPFactoryRemoveInstance(_CFPFactory *factory) {
237 /* MF:!!! Assert that _instanceCount > 0. */
238 factory->_instanceCount--;
239 if (factory->_plugIn) _CFPlugInRemovePlugInInstance(factory->_plugIn);
240 if (factory->_instanceCount == 0 && !factory->_enabled) _CFPFactoryDeallocate(factory);
241 }