]> git.saurik.com Git - apple/cf.git/blame - Preferences.subproj/CFApplicationPreferences.c
CF-368.28.tar.gz
[apple/cf.git] / Preferences.subproj / CFApplicationPreferences.c
CommitLineData
d8925383
A
1/*
2 * Copyright (c) 2005 Apple Computer, 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/* CFApplicationPreferences.c
24 Copyright 1998-2002, Apple, Inc. All rights reserved.
25 Responsibility: Chris Parker
26*/
27
28#include <CoreFoundation/CFPreferences.h>
29#include "CFInternal.h"
30#include <CoreFoundation/CFUniChar.h>
31#include <CoreFoundation/CFNumber.h>
32
0ae65c4b 33
d8925383
A
34static Boolean _CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences *self);
35void _CFPreferencesDomainSetMultiple(CFPreferencesDomainRef domain, CFDictionaryRef dict);
36static void updateDictRep(_CFApplicationPreferences *self);
37Boolean _CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences *self, CFPreferencesDomainRef domain);
38
39static void *__CFInsertionDomain = NULL;
40static CFDictionaryRef __CFInsertion = NULL;
41
42// Bindings internals
43extern CFSpinLock_t userDefaultsLock;
44extern void *userDefaults;
45
46// Management externals
47extern Boolean _CFPreferencesManagementActive;
48
49
50#define CF_OBJC_KVO_WILLCHANGE(obj, sel)
51#define CF_OBJC_KVO_DIDCHANGE(obj, sel)
52
53
54// Right now, nothing is getting destroyed pretty much ever. We probably don't want this to be the case, but it's very tricky - domains live in the cache as well as a given application's preferences, and since they're not CFTypes, there's no reference count. Also, it's not clear we ever want domains destroyed. When they're synchronized, they clear their internal state (to force reading from the disk again), so they're not very big.... REW, 12/17/98
55
56CFPropertyListRef CFPreferencesCopyAppValue(CFStringRef key, CFStringRef appName) {
57 _CFApplicationPreferences *standardPrefs;
58 CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
59 CFAssert1(key != NULL, __kCFLogAssertion, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__);
60
61 standardPrefs = _CFStandardApplicationPreferences(appName);
62 return standardPrefs ? _CFApplicationPreferencesCreateValueForKey(standardPrefs, key) : NULL;
63}
64
65CF_EXPORT Boolean CFPreferencesAppBooleanValue(CFStringRef key, CFStringRef appName, Boolean *keyExistsAndHasValidFormat) {
66 CFPropertyListRef value;
67 Boolean result, valid;
68 CFTypeID typeID = 0;
69 CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
70 CFAssert1(key != NULL, __kCFLogAssertion, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__);
71
72 if (!keyExistsAndHasValidFormat) {
73 keyExistsAndHasValidFormat = &valid;
74 }
75 value = CFPreferencesCopyAppValue(key, appName);
76 if (!value) {
77 *keyExistsAndHasValidFormat = false;
78 return false;
79 }
80 typeID = CFGetTypeID(value);
81 if (typeID == CFStringGetTypeID()) {
82 if (CFStringCompare(value, CFSTR("true"), kCFCompareCaseInsensitive) == kCFCompareEqualTo || CFStringCompare(value, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
83 *keyExistsAndHasValidFormat = true;
84 result = true;
85 } else if (CFStringCompare(value, CFSTR("false"), kCFCompareCaseInsensitive) == kCFCompareEqualTo || CFStringCompare(value, CFSTR("NO"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
86 *keyExistsAndHasValidFormat = true;
87 result = false;
88 } else {
89 *keyExistsAndHasValidFormat = false;
90 result = false;
91 }
92 } else if (typeID == CFNumberGetTypeID()) {
93 if (CFNumberIsFloatType(value)) {
94 *keyExistsAndHasValidFormat = false;
95 result = false;
96 } else {
97 int i;
98 *keyExistsAndHasValidFormat = true;
99 CFNumberGetValue(value, kCFNumberIntType, &i);
100 result = (i == 0) ? false : true;
101 }
102 } else if (typeID == CFBooleanGetTypeID()) {
103 result = (value == kCFBooleanTrue);
104 *keyExistsAndHasValidFormat = true;
105 } else {
106 // Unknown type
107 result = false;
108 *keyExistsAndHasValidFormat = false;
109 }
110 CFRelease(value);
111 return result;
112}
113
114__private_extern__ CFIndex CFPreferencesAppIntegerValue(CFStringRef key, CFStringRef appName, Boolean *keyExistsAndHasValidFormat) {
115 CFPropertyListRef value;
116 CFIndex result;
117 CFTypeID typeID = 0;
118 Boolean valid;
119 CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
120 CFAssert1(key != NULL, __kCFLogAssertion, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__);
121
122 value = CFPreferencesCopyAppValue(key, appName);
123 if (!keyExistsAndHasValidFormat) {
124 keyExistsAndHasValidFormat = &valid;
125 }
126 if (!value) {
127 *keyExistsAndHasValidFormat = false;
128 return 0;
129 }
130 typeID = CFGetTypeID(value);
131 if (typeID == CFStringGetTypeID()) {
132 CFIndex charIndex = 0;
133 SInt32 intVal;
134 CFStringInlineBuffer buf;
135 Boolean success;
136 CFStringInitInlineBuffer(value, &buf, CFRangeMake(0, CFStringGetLength(value)));
137 success = __CFStringScanInteger(&buf, NULL, &charIndex, false, &intVal);
138 *keyExistsAndHasValidFormat = (success && charIndex == CFStringGetLength(value));
139 result = (*keyExistsAndHasValidFormat) ? intVal : 0;
140 } else if (typeID == CFNumberGetTypeID()) {
141 *keyExistsAndHasValidFormat = !CFNumberIsFloatType(value);
142 if (*keyExistsAndHasValidFormat) {
143 CFNumberGetValue(value, kCFNumberCFIndexType, &result);
144 } else {
145 result = 0;
146 }
147 } else {
148 // Unknown type
149 result = 0;
150 *keyExistsAndHasValidFormat = false;
151 }
152 CFRelease(value);
153 return result;
154}
155
156Boolean CFPreferencesGetAppBooleanValue(CFStringRef key, CFStringRef appName, Boolean *keyExistsAndHasValidFormat) {
157 CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
158 CFAssert1(key != NULL, __kCFLogAssertion, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__);
159 return CFPreferencesAppBooleanValue(key, appName, keyExistsAndHasValidFormat);
160}
161
162CFIndex CFPreferencesGetAppIntegerValue(CFStringRef key, CFStringRef appName, Boolean *keyExistsAndHasValidFormat) {
163 CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
164 CFAssert1(key != NULL, __kCFLogAssertion, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__);
165 return CFPreferencesAppIntegerValue(key, appName, keyExistsAndHasValidFormat);
166}
167
168void CFPreferencesSetAppValue(CFStringRef key, CFTypeRef value, CFStringRef appName) {
169 _CFApplicationPreferences *standardPrefs;
170 CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
171 CFAssert1(key != NULL, __kCFLogAssertion, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__);
172
173 standardPrefs = _CFStandardApplicationPreferences(appName);
174 if (standardPrefs) {
175 if (value) _CFApplicationPreferencesSet(standardPrefs, key, value);
176 else _CFApplicationPreferencesRemove(standardPrefs, key);
177 }
178}
179
180
181static CFSpinLock_t __CFApplicationPreferencesLock = 0; // Locks access to __CFStandardUserPreferences
182static CFMutableDictionaryRef __CFStandardUserPreferences = NULL; // Mutable dictionary; keys are app names, values are _CFApplicationPreferences
183
184Boolean CFPreferencesAppSynchronize(CFStringRef appName) {
185 _CFApplicationPreferences *standardPrefs;
186 Boolean result;
187 CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
188 __CFPreferencesCheckFormatType();
189
190 // Do not call _CFStandardApplicationPreferences(), as we do not want to create the preferences only to synchronize
191 __CFSpinLock(&__CFApplicationPreferencesLock);
192 if (__CFStandardUserPreferences) {
193 standardPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName);
194 } else {
195 standardPrefs = NULL;
196 }
197
198 result = standardPrefs ? _CFApplicationPreferencesSynchronizeNoLock(standardPrefs) : _CFSynchronizeDomainCache();
199 __CFSpinUnlock(&__CFApplicationPreferencesLock);
200 return result;
201}
202
203void CFPreferencesFlushCaches(void) {
204 CFAllocatorRef alloc = __CFPreferencesAllocator();
205 __CFSpinLock(&__CFApplicationPreferencesLock);
206 if (__CFStandardUserPreferences) {
207 _CFApplicationPreferences **prefsArray, *prefsBuf[32];
208 CFIndex idx, count = CFDictionaryGetCount(__CFStandardUserPreferences);
209 if (count < 32) {
210 prefsArray = prefsBuf;
211 } else {
212 prefsArray = _CFAllocatorAllocateGC(alloc, count * sizeof(_CFApplicationPreferences *), 0);
213 }
214 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences, NULL, (const void **)prefsArray);
215
216 __CFSpinUnlock(&__CFApplicationPreferencesLock);
217 // DeallocateApplicationPreferences needs the lock
218 for (idx = 0; idx < count; idx ++) {
219 _CFApplicationPreferences *appPrefs = prefsArray[idx];
220 _CFApplicationPreferencesSynchronize(appPrefs);
221 _CFDeallocateApplicationPreferences(appPrefs);
222 }
223 __CFSpinLock(&__CFApplicationPreferencesLock);
224
225 CFRelease(__CFStandardUserPreferences);
226 __CFStandardUserPreferences = NULL;
227 if(prefsArray != prefsBuf) _CFAllocatorDeallocateGC(alloc, prefsArray);
228 }
229 __CFSpinUnlock(&__CFApplicationPreferencesLock);
230 _CFPreferencesPurgeDomainCache();
231}
232
233// quick message to indicate that the given domain has changed, and we should go through and invalidate any dictReps that involve this domain.
234void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDomain) {
235 CFAllocatorRef alloc = __CFPreferencesAllocator();
236 __CFSpinLock(&__CFApplicationPreferencesLock);
237 if(__CFStandardUserPreferences) { // only grovel over the prefs if there's something there to grovel
238 _CFApplicationPreferences **prefsArray, *prefsBuf[32];
239 CFIndex idx, count = CFDictionaryGetCount(__CFStandardUserPreferences);
240 if(count < 32) {
241 prefsArray = prefsBuf;
242 } else {
243 prefsArray = _CFAllocatorAllocateGC(alloc, count * sizeof(_CFApplicationPreferences *), 0);
244 }
245 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences, NULL, (const void **)prefsArray);
246 // For this operation, giving up the lock is the last thing we want to do, so use the modified flavor of _CFApplicationPreferencesContainsDomain
247 for(idx = 0; idx < count; idx++) {
248 _CFApplicationPreferences *appPrefs = prefsArray[idx];
249 if(_CFApplicationPreferencesContainsDomainNoLock(appPrefs, changedDomain)) {
250 updateDictRep(appPrefs);
251 }
252 }
253 if(prefsArray != prefsBuf) _CFAllocatorDeallocateGC(alloc, prefsArray);
254 }
255 __CFSpinUnlock(&__CFApplicationPreferencesLock);
256}
257
258
259// Begin ported code from NSUserDefaults.m
260
261/*************** Constants ***************/
262
263// NSString * const NSUserDefaultsDidChangeNotification = @"NSUserDefaultsDidChangeNotification";
264
265static void updateDictRep(_CFApplicationPreferences *self) {
266 if (self->_dictRep) {
267 CFRelease(self->_dictRep);
268 self->_dictRep = NULL;
269 }
270}
271
272static void __addKeysAndValues(const void *key, const void *value, void *context) {
273 CFDictionarySetValue(context, key, value);
274}
275
276static void computeDictRep(_CFApplicationPreferences *self) {
277 CFAllocatorRef alloc = __CFPreferencesAllocator();
278 CFMutableArrayRef searchList = self->_search;
279 CFIndex idx;
280 CFIndex cnt = CFArrayGetCount(searchList);
281 CFDictionaryRef subdomainDict;
282
283 if (self->_dictRep) {
284 CFRelease(self->_dictRep);
285 }
286 self->_dictRep = CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, & kCFTypeDictionaryValueCallBacks);
287 _CFDictionarySetCapacity(self->_dictRep, 160); // avoid lots of rehashing
288
289 if (!self->_dictRep) return;
290 if (0 == cnt) return;
291
292 // For each subdomain triplet in the domain, iterate over dictionaries, adding them if necessary to the dictRep
293 for (idx = cnt; idx--;) {
294 CFPreferencesDomainRef domain = (CFPreferencesDomainRef)CFArrayGetValueAtIndex(searchList, idx);
295
296 if (!domain) continue;
297
298 subdomainDict = _CFPreferencesDomainDeepCopyDictionary(domain);
299 if(subdomainDict) {
300 CFDictionaryApplyFunction(subdomainDict, __addKeysAndValues, self->_dictRep);
301 CFRelease(subdomainDict);
302 }
303
304 if (__CFInsertionDomain == domain && __CFInsertion) {
305 CFDictionaryApplyFunction(__CFInsertion, __addKeysAndValues, self->_dictRep);
306 }
307 }
308}
309
310CFTypeRef _CFApplicationPreferencesSearchDownToDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef stopper, CFStringRef key) {
311 CFTypeRef value = NULL;
312 __CFSpinLock(&__CFApplicationPreferencesLock);
313 CFIndex idx, cnt;
314 cnt = CFArrayGetCount(self->_search);
315 for (idx = 0; idx < cnt; idx++) {
316 CFPreferencesDomainRef domain = (CFPreferencesDomainRef)CFArrayGetValueAtIndex(self->_search, idx);
317 if (domain == stopper) break;
318 value = _CFPreferencesDomainCreateValueForKey(domain, key);
319 if (value) break;
320 }
321 __CFSpinUnlock(&__CFApplicationPreferencesLock);
322 return value;
323}
324
325
326void _CFApplicationPreferencesUpdate(_CFApplicationPreferences *self) {
327 __CFSpinLock(&__CFApplicationPreferencesLock);
328 updateDictRep(self);
329 __CFSpinUnlock(&__CFApplicationPreferencesLock);
330}
331
332__private_extern__ CFDictionaryRef __CFApplicationPreferencesCopyCurrentState(void) {
333 CFDictionaryRef result;
334 _CFApplicationPreferences *self = _CFStandardApplicationPreferences(kCFPreferencesCurrentApplication);
335 __CFSpinLock(&__CFApplicationPreferencesLock);
336 if (!self->_dictRep) {
337 computeDictRep(self);
338 }
339 result = CFDictionaryCreateCopy(kCFAllocatorSystemDefault, self->_dictRep);
340 __CFSpinUnlock(&__CFApplicationPreferencesLock);
341 return result;
342}
343
344// CACHING here - we will only return a value as current as the last time computeDictRep() was called
345CFTypeRef _CFApplicationPreferencesCreateValueForKey(_CFApplicationPreferences *self, CFStringRef defaultName) {
346 CFTypeRef result;
347 __CFSpinLock(&__CFApplicationPreferencesLock);
348 if (!self->_dictRep) {
349 computeDictRep(self);
350 }
351 result = (self->_dictRep) ? (CFTypeRef )CFDictionaryGetValue(self->_dictRep, defaultName) : NULL;
352 if (result) {
353 CFRetain(result);
354 }
355 __CFSpinUnlock(&__CFApplicationPreferencesLock);
356 return result;
357}
358
359void _CFApplicationPreferencesSet(_CFApplicationPreferences *self, CFStringRef defaultName, CFTypeRef value) {
360 CFPreferencesDomainRef applicationDomain;
361 void *defs = NULL;
362 __CFSpinLock(&userDefaultsLock);
363 defs = userDefaults;
364 __CFSpinUnlock(&userDefaultsLock);
365
366 CF_OBJC_KVO_WILLCHANGE(defs, defaultName);
367 __CFSpinLock(&__CFApplicationPreferencesLock);
368 applicationDomain = _CFPreferencesStandardDomain(self->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
369 if(applicationDomain) {
370 _CFPreferencesDomainSet(applicationDomain, defaultName, value);
371 if (CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), applicationDomain)) {
372 // Expensive; can't we just check the relevant value throughout the appropriate sets of domains? -- REW, 7/19/99
373 updateDictRep(self);
374 }
375 }
376 __CFSpinUnlock(&__CFApplicationPreferencesLock);
377 CF_OBJC_KVO_DIDCHANGE(defs, defaultName);
378}
379
380void _CFApplicationPreferencesRemove(_CFApplicationPreferences *self, CFStringRef defaultName) {
381 CFPreferencesDomainRef appDomain;
4c91a73d
A
382 void *defs = NULL;
383 __CFSpinLock(&userDefaultsLock);
384 defs = userDefaults;
385 __CFSpinUnlock(&userDefaultsLock);
386 CF_OBJC_KVO_WILLCHANGE(defs, defaultName);
d8925383
A
387 __CFSpinLock(&__CFApplicationPreferencesLock);
388 appDomain = _CFPreferencesStandardDomain(self->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
389 if(appDomain) {
390 _CFPreferencesDomainSet(appDomain, defaultName, NULL);
391 if (CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), appDomain)) {
392 // If key exists, it will be in the _dictRep (but possibly overridden)
393 updateDictRep(self);
394 }
395 }
396 __CFSpinUnlock(&__CFApplicationPreferencesLock);
4c91a73d 397 CF_OBJC_KVO_DIDCHANGE(defs, defaultName);
d8925383
A
398}
399
400static Boolean _CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences *self) {
401 Boolean success = _CFSynchronizeDomainCache();
402 if (self->_dictRep) {
403 CFRelease(self->_dictRep);
404 self->_dictRep = NULL;
405 }
406 return success;
407}
408
409Boolean _CFApplicationPreferencesSynchronize(_CFApplicationPreferences *self) {
410 Boolean result;
411 __CFPreferencesCheckFormatType();
412 __CFSpinLock(&__CFApplicationPreferencesLock);
413 result = _CFApplicationPreferencesSynchronizeNoLock(self);
414 __CFSpinUnlock(&__CFApplicationPreferencesLock);
415 return result;
416}
417
418// appName should not be kCFPreferencesCurrentApplication going in to this call
419_CFApplicationPreferences *_CFApplicationPreferencesCreateWithUser(CFStringRef userName, CFStringRef appName) {
420 CFAllocatorRef alloc = __CFPreferencesAllocator();
421 _CFApplicationPreferences *self = CFAllocatorAllocate(alloc, sizeof(_CFApplicationPreferences), 0);
422 if (self) {
423 self->_dictRep = NULL;
424 self->_appName = CFRetain(appName);
425 self->_search = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
426 if (!self->_search) {
427 CFAllocatorDeallocate(alloc, self);
428 CFRelease(appName);
429 self = NULL;
430 }
431 }
432 return self;
433}
434
435// Do NOT release the domain after adding it to the array; domain_expression should not return a retained object -- REW, 8/26/99
436#define ADD_DOMAIN(domain_expression) domain = domain_expression; if (domain) {CFArrayAppendValue(search, domain);}
437void _CFApplicationPreferencesSetStandardSearchList(_CFApplicationPreferences *appPreferences) {
438 /* Now we add the standard domains; they are, in order:
439 this user, this app, this host
440 this user, this app, any host
441 this user, any app, this host
442 this user, any app, any host
443 any user, this app, this host
444 any user, this app, any host
445 any user, any app, this host
446 any user, any app, any host
447
448 note: for MacOS 8, we only add:
449 this user, this app, this host
450 this user, any app, this host
451 any user, this app, this host
452 any user, any app, this host
453 */
454 CFPreferencesDomainRef domain;
455 CFMutableArrayRef search = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
456 if (!search) {
457 // couldn't allocate memory!
458 return;
459 }
460
461 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences->_appName, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost));
462 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost));
463 __CFInsertionDomain = _CFPreferencesStandardDomain(kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
464 ADD_DOMAIN(__CFInsertionDomain);
465 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost));
466 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences->_appName, kCFPreferencesAnyUser, kCFPreferencesCurrentHost));
467 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences->_appName, kCFPreferencesAnyUser, kCFPreferencesAnyHost));
468 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication, kCFPreferencesAnyUser, kCFPreferencesCurrentHost));
469 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication, kCFPreferencesAnyUser, kCFPreferencesAnyHost));
470
471 _CFApplicationPreferencesSetSearchList(appPreferences, search);
472 CFRelease(search);
473}
474#undef ADD_DOMAIN
475
476
477__private_extern__ _CFApplicationPreferences *_CFStandardApplicationPreferences(CFStringRef appName) {
478 _CFApplicationPreferences *appPreferences;
479// CFAssert(appName != kCFPreferencesAnyApplication, __kCFLogAssertion, "Cannot use any of the CFPreferences...App... functions with an appName of kCFPreferencesAnyApplication");
480 __CFSpinLock(&__CFApplicationPreferencesLock);
481 if (!__CFStandardUserPreferences) {
482 __CFStandardUserPreferences = CFDictionaryCreateMutable(NULL, 0, & kCFTypeDictionaryKeyCallBacks, NULL);
483 }
484 if (!__CFStandardUserPreferences) {
485 // Couldn't create
486 __CFSpinUnlock(&__CFApplicationPreferencesLock);
487 return NULL;
488 }
489 if ((appPreferences = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName)) == NULL ) {
490 appPreferences = _CFApplicationPreferencesCreateWithUser(kCFPreferencesCurrentUser, appName);
491 CFDictionarySetValue(__CFStandardUserPreferences, appName, appPreferences);
492 __CFSpinUnlock(&__CFApplicationPreferencesLock);
493 _CFApplicationPreferencesSetStandardSearchList(appPreferences);
494 } else {
495 __CFSpinUnlock(&__CFApplicationPreferencesLock);
496 }
497 return appPreferences;
498}
499
500// Exclusively for Foundation's use
501void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences *appPrefs, CFStringRef appName) {
502 __CFSpinLock(&__CFApplicationPreferencesLock);
503 if (!__CFStandardUserPreferences) {
504 __CFStandardUserPreferences = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
505 CFDictionarySetValue(__CFStandardUserPreferences, appName, appPrefs);
506 __CFSpinUnlock(&__CFApplicationPreferencesLock);
507 } else {
508 _CFApplicationPreferences *oldPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName);
509 CFDictionarySetValue(__CFStandardUserPreferences, appName, appPrefs);
510 __CFSpinUnlock(&__CFApplicationPreferencesLock);
511 if (oldPrefs) {
512 _CFDeallocateApplicationPreferences(oldPrefs);
513 }
514 }
515}
516
517
518void _CFDeallocateApplicationPreferences(_CFApplicationPreferences *self) {
519 CFAllocatorRef alloc = __CFPreferencesAllocator();
520 _CFApplicationPreferences *cachedPrefs = NULL;
521 __CFSpinLock(&__CFApplicationPreferencesLock);
522
523 // Get us out of the cache before destroying!
524 if (__CFStandardUserPreferences) {
525 cachedPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, self->_appName);
526 }
527 if (cachedPrefs == self) {
528 CFDictionaryRemoveValue(__CFStandardUserPreferences, self->_appName);
529 }
530
531 if (self->_dictRep) CFRelease(self->_dictRep);
532 CFRelease(self->_search);
533 CFRelease(self->_appName);
534 CFAllocatorDeallocate(alloc, self);
535 __CFSpinUnlock(&__CFApplicationPreferencesLock);
536}
537
538// For Foundation's use
539CFDictionaryRef _CFApplicationPreferencesCopyRepresentationWithHint(_CFApplicationPreferences *self, CFDictionaryRef hint) {
540 CFDictionaryRef dict;
541 __CFSpinLock(&__CFApplicationPreferencesLock);
542 if (!self->_dictRep) {
543 computeDictRep(self);
544 }
545 if (self->_dictRep && (self->_dictRep != hint)) {
546 CFRetain(self->_dictRep);
547 }
548 dict = self->_dictRep;
549 __CFSpinUnlock(&__CFApplicationPreferencesLock);
550 return dict;
551}
552
553// For Foundation's use; does not do what it would seem to from the name
554CFDictionaryRef _CFApplicationPreferencesCopyRepresentation3(_CFApplicationPreferences *self, CFDictionaryRef hint, CFDictionaryRef insertion, CFPreferencesDomainRef afterDomain) {
555 __CFSpinLock(&__CFApplicationPreferencesLock);
556 if (0 == self && 0 == hint && 0 == afterDomain) {
557 // This is so so gross.
558 if (__CFInsertion) CFRelease(__CFInsertion);
559 __CFInsertion = insertion ? CFRetain(insertion) : NULL;
560 }
561 __CFSpinUnlock(&__CFApplicationPreferencesLock);
562 return 0;
563}
564
565CF_EXPORT
566CFDictionaryRef _CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences *self) {
567 return _CFApplicationPreferencesCopyRepresentationWithHint(self, NULL);
568}
569
570__private_extern__ void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences *self, CFArrayRef newSearchList) {
571 CFIndex idx, count;
572 __CFSpinLock(&__CFApplicationPreferencesLock);
573 CFArrayRemoveAllValues(self->_search);
574 count = CFArrayGetCount(newSearchList);
575 for (idx = 0; idx < count; idx ++) {
576 CFArrayAppendValue(self->_search, CFArrayGetValueAtIndex(newSearchList, idx));
577 }
578 updateDictRep(self);
579 __CFSpinUnlock(&__CFApplicationPreferencesLock);
580}
581
582void CFPreferencesAddSuitePreferencesToApp(CFStringRef appName, CFStringRef suiteName) {
583 _CFApplicationPreferences *appPrefs;
584
585 appPrefs = _CFStandardApplicationPreferences(appName);
586 _CFApplicationPreferencesAddSuitePreferences(appPrefs, suiteName);
587}
588
589void _CFApplicationPreferencesAddSuitePreferences(_CFApplicationPreferences *appPrefs, CFStringRef suiteName) {
590 CFPreferencesDomainRef domain;
591 CFIndex idx;
592 CFRange range;
593
594 // Find where to insert the new suite
595 __CFSpinLock(&__CFApplicationPreferencesLock);
596 domain = _CFPreferencesStandardDomain(appPrefs->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
597 range.location = 0;
598 range.length = CFArrayGetCount(appPrefs->_search);
599 idx = domain ? CFArrayGetFirstIndexOfValue(appPrefs->_search, range, domain) : kCFNotFound;
600 __CFSpinUnlock(&__CFApplicationPreferencesLock);
601 idx ++; // We want just below the app domain. Coincidentally, this gives us the top of the list if the app domain has been removed.
602 domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
603 if (domain) {
604 __CFSpinLock(&__CFApplicationPreferencesLock);
605 CFArrayInsertValueAtIndex(appPrefs->_search, idx, domain);
606 __CFSpinUnlock(&__CFApplicationPreferencesLock);
607 range.length ++;
608 }
609 domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
610 if (domain) {
611 __CFSpinLock(&__CFApplicationPreferencesLock);
612 CFArrayInsertValueAtIndex(appPrefs->_search, idx, domain);
613 __CFSpinUnlock(&__CFApplicationPreferencesLock);
614 range.length ++;
615 }
616
617 // Now the AnyUser domains
618 domain = _CFPreferencesStandardDomain(appPrefs->_appName, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
619 idx = domain ? CFArrayGetFirstIndexOfValue(appPrefs->_search, range, domain) : kCFNotFound;
620 if (idx == kCFNotFound) {
621 // Someone blew away the app domain. Can only happen through -[NSUserDefaults setSearchList:]. For the any user case, we look for right below the global domain
622 // Can this happen anymore? -[NSUserDefaults setSearchList:] is bailing. -- ctp - - 3 Jan 2002
623 domain = _CFPreferencesStandardDomain(kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
624 idx = domain ? CFArrayGetFirstIndexOfValue(appPrefs->_search, range, domain) : kCFNotFound;
625 if (idx == kCFNotFound) {
626 // Try the "any host" choice
627 domain = _CFPreferencesStandardDomain(kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
628 idx = domain ? CFArrayGetFirstIndexOfValue(appPrefs->_search, range, domain) : kCFNotFound;
629 if (idx == kCFNotFound) {
630 // We give up; put the new domains at the bottom
631 idx = CFArrayGetCount(appPrefs->_search) - 1;
632 }
633 }
634 }
635 idx ++;
636 domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
637 if (domain) {
638 __CFSpinLock(&__CFApplicationPreferencesLock);
639 CFArrayInsertValueAtIndex(appPrefs->_search, idx, domain);
640 __CFSpinUnlock(&__CFApplicationPreferencesLock);
641 }
642 domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
643 if (domain) {
644 __CFSpinLock(&__CFApplicationPreferencesLock);
645 CFArrayInsertValueAtIndex(appPrefs->_search, idx, domain);
646 __CFSpinUnlock(&__CFApplicationPreferencesLock);
647 }
648 __CFSpinLock(&__CFApplicationPreferencesLock);
649 updateDictRep(appPrefs);
650 __CFSpinUnlock(&__CFApplicationPreferencesLock);
651}
652
653void CFPreferencesRemoveSuitePreferencesFromApp(CFStringRef appName, CFStringRef suiteName) {
654 _CFApplicationPreferences *appPrefs;
655
656 appPrefs = _CFStandardApplicationPreferences(appName);
657
658 _CFApplicationPreferencesRemoveSuitePreferences(appPrefs, suiteName);
659}
660
661void _CFApplicationPreferencesRemoveSuitePreferences(_CFApplicationPreferences *appPrefs, CFStringRef suiteName) {
662 CFPreferencesDomainRef domain;
663
664 __CFSpinLock(&__CFApplicationPreferencesLock);
665 domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
666 __CFSpinUnlock(&__CFApplicationPreferencesLock);
667 if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain);
668
669 __CFSpinLock(&__CFApplicationPreferencesLock);
670 domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
671 __CFSpinUnlock(&__CFApplicationPreferencesLock);
672 if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain);
673
674 __CFSpinLock(&__CFApplicationPreferencesLock);
675 domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
676 __CFSpinUnlock(&__CFApplicationPreferencesLock);
677 if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain);
678
679 __CFSpinLock(&__CFApplicationPreferencesLock);
680 domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
681 __CFSpinUnlock(&__CFApplicationPreferencesLock);
682 if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain);
683}
684
685void _CFApplicationPreferencesAddDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain, Boolean addAtTop) {
686 __CFSpinLock(&__CFApplicationPreferencesLock);
687 if (addAtTop) {
688 CFArrayInsertValueAtIndex(self->_search, 0, domain);
689 } else {
690 CFArrayAppendValue(self->_search, domain);
691 }
692 updateDictRep(self);
693 __CFSpinUnlock(&__CFApplicationPreferencesLock);
694}
695
696Boolean _CFApplicationPreferencesContainsDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) {
697 Boolean result;
698 __CFSpinLock(&__CFApplicationPreferencesLock);
699 result = CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), domain);
700 __CFSpinUnlock(&__CFApplicationPreferencesLock);
701 return result;
702}
703
704Boolean _CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) {
705 Boolean result;
706 result = CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), domain);
707 return result;
708}
709
710void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) {
711 CFIndex idx;
712 CFRange range;
713 __CFSpinLock(&__CFApplicationPreferencesLock);
714 range.location = 0;
715 range.length = CFArrayGetCount(self->_search);
716 while ((idx = CFArrayGetFirstIndexOfValue(self->_search, range, domain)) != kCFNotFound) {
717 CFArrayRemoveValueAtIndex(self->_search, idx);
718 range.location = idx;
719 range.length = range.length - idx - 1;
720 }
721 updateDictRep(self);
722 __CFSpinUnlock(&__CFApplicationPreferencesLock);
723}
724
725