]>
Commit | Line | Data |
---|---|---|
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 | 32 | static CFSpinLock_t CFPlugInGlobalDataLock = CFSpinLockInit; |
9ce05555 A |
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); | |
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 | ||
46 | static 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 | ||
64 | static 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 | ||
84 | static _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 | } |