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