Esempio n. 1
0
extern pascal void CFQPropertyListDeepApplyFunction(CFPropertyListRef propList, 
													CFQPropertyListDeepApplierFunction func,
													void *context)
	// See comment in header.
{
	assert(propList != NULL);
	assert(func     != NULL);
	
	// Call "func" for this node.
	
	func(propList, context);
	
	// If this node is a dictionary or an array, call func for 
	// each element.
	
	if ( CFGetTypeID(propList) == CFDictionaryGetTypeID() ) {
		CFIndex count;
		CFIndex index;
		
		count = CFDictionaryGetCount( (CFDictionaryRef) propList);
		if (count > 0) {
			const void **keys;

			keys = (const void **) malloc( count * sizeof(const void *));
			if (keys != NULL) {
				CFDictionaryGetKeysAndValues( (CFDictionaryRef) propList, keys, NULL);
				
				for (index = 0; index < count; index++) {
					CFQPropertyListDeepApplyFunction(CFDictionaryGetValue( (CFDictionaryRef) propList, keys[index]), func, context);
				}
				free(keys);
			}
		}
	} else if ( CFGetTypeID(propList) == CFArrayGetTypeID() ) {
		CFIndex count;
		long    index;
		
		count = CFArrayGetCount( (CFArrayRef) propList);
		for (index = 0; index < count; index++) {
			CFQPropertyListDeepApplyFunction(CFArrayGetValueAtIndex( (CFArrayRef) propList, index), func, context);
		}
	}
}
Esempio n. 2
0
static SInt32 TotalAllRefCounts(SCPreferencesRef prefsRef, CFArrayRef allKeys)
	// Given a connection to the SCF preferences database and an array 
	// of preference keys, this routine calculates the total of all 
	// of the reference counts of all of the nodes in all of the SCF 
	// preferences.  I use this routine to check for reference count leaks 
	// in my use of the SCF preferences database.
{
	CFIndex keyCount;
	CFIndex keyIndex;
	SInt32	result;
	
	result = 0;
	keyCount = CFArrayGetCount(allKeys);
	for (keyIndex = 0; keyIndex < keyCount; keyIndex++) {
		CFPropertyListRef thisPref;
		
		thisPref = SCPreferencesGetValue(prefsRef, (CFStringRef) CFArrayGetValueAtIndex(allKeys, keyIndex));	// C++ requires cast
		CFQPropertyListDeepApplyFunction(thisPref, RefCounter, (void *) &result );
	}
	return result;
}
Esempio n. 3
0
static void LeakTest(TestFunc tester)
	// Given a test name and a pointer to a test function, 
	// this routine calls the test function repeatedly to check 
	// for SCF preferences reference count leaks.
{
	OSStatus 			err;
	SCPreferencesRef 	prefsRef;
	CFArrayRef 			allKeys;
	int					i;
	SInt32				startCount;
	SInt32				endCount;
	
	// This is kinda cheesy.  We need to use the same SCPreferencesRef 
	// that MoreSCF uses because otherwise we can't see the reference 
	// count changes done by MoreSCF.  Ideally, we wouldn't want to run 
	// within a MoreSCOpen/MoreSCClose pair because then our changes 
	// aren't necessarily being committed to the database.  However, 
	// given the current MoreSCF architecture, where the SCPreferenceRef 
	// is only valid inside the MoreSCOpen/MoreSCClose pair, that's 
	// exactly what we have to do.

	allKeys = NULL;
	
	err = MoreSCOpen(false, false);
	if (err == noErr) {
		prefsRef = MoreSCGetSCPreferencesRef();
	}

	// Now get a copy of the array of all keys in the database.  
	// We make this copy using CFPropertyListCreateDeepCopy so we 
	// know that it's completely independent of the SCF.
	
	if (err == noErr) {
		CFArrayRef allKeysOrig;
		
		allKeysOrig = NULL;

		allKeysOrig = SCPreferencesCopyKeyList(prefsRef);
		if (allKeysOrig == NULL) {
			err = SCError();
		}
		if (err == noErr) {
			allKeys = (CFArrayRef) CFPropertyListCreateDeepCopy(NULL, allKeysOrig, kCFPropertyListMutableContainersAndLeaves);	// C++ requires cast
			if (allKeys == NULL) {
				err = coreFoundationUnknownErr;
			}
		}
		
		CFQRelease(allKeysOrig);
	}

	// Now do the reference counting test.  Call the tester function
	// a few times to allow the refcounts to stabilise.  Then get 
	// a summ of all the nodes in all of the keys in SCF.  Then 
	// run the test a 10 more times and get another count.  If 
	// the counts are different, we're in trouble.
	
	if (err == noErr) {
		for (i = 0; i < 3; i++) {
			tester();
		}
		
		startCount = TotalAllRefCounts(prefsRef, allKeys);
		
		for (i = 0; i < 10; i++) {
			tester();
		}
		
		endCount = TotalAllRefCounts(prefsRef, allKeys);
		
		if (startCount != endCount) {
			CFIndex keyCount;
			CFIndex keyIndex;
			
			fprintf(stderr, "*** Leaked %ld reference counts.\n", endCount - startCount);

			keyCount = CFArrayGetCount(allKeys);
			for (keyIndex = 0; keyIndex < keyCount; keyIndex++) {
				CFPropertyListRef thisPref;

				// The commented out code is only needed when you're actively 
				// trying to track down a leak.  Given that leaks are rare 
				// I decided against making a proper architecture for this. 
				// Just uncomment the code and modify it appropriately.
				
				startCount = 0;
				thisPref = SCPreferencesGetValue(prefsRef, (CFStringRef) CFArrayGetValueAtIndex(allKeys, keyIndex));	// C++ requires cast
				CFQPropertyListDeepApplyFunction(thisPref, RefCounter, (void *) &startCount );
//				if (keyIndex == 0) {
//					fprintf(stderr, "*** BEFORE ***\n");
//					PrintPropertyList(thisPref);
//				}

				tester();

				endCount = 0;
				thisPref = SCPreferencesGetValue(prefsRef, (CFStringRef) CFArrayGetValueAtIndex(allKeys, keyIndex));	// C++ requires cast
				CFQPropertyListDeepApplyFunction(thisPref, RefCounter, (void *) &endCount );
//				if (keyIndex == 0) {
//					fprintf(stderr, "*** AFTER ***\n");
//					PrintPropertyList(thisPref);
//				}
				
				if (startCount != endCount) {
					fprintf(stderr, "*** Leaked %ld reference counts in set number %ld\n", endCount - startCount, keyIndex);
					CFShow(CFArrayGetValueAtIndex(allKeys, keyIndex));
				}
			}
		}
	}

	MoreSCClose(&err, false);

	CFQRelease(allKeys);

    if (err != noErr) {
        fprintf(stderr, "*** Failed with error %ld!\n", err);
    }
}