New file.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1651 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Andrew McCallum 1996-07-15 18:42:52 +00:00
parent 52441fecef
commit a601e7efea
5 changed files with 1101 additions and 0 deletions

View file

@ -0,0 +1,181 @@
/* Interface for <Class> for GNUStep
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Written by: Georg Tuparev, EMBL & Academia Naturalis,
Heidelberg, Germany
Tuparev@EMBL-Heidelberg.de
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __NSUserDefaults_h_OBJECTS_INCLUDE
#define __NSUserDefaults_h_OBJECTS_INCLUDE
#ifdef NeXT
#import <foundation/NSObject.h>
#import <foundation/NSString.h>
#else
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
#endif /* NeXT */
@class NSArray;
@class NSMutableArray;
@class NSDictionary;
@class NSMutableDictionary;
@class NSData;
/* Standard domains */
extern NSString* NSArgumentDomain;
extern NSString* NSGlobalDomain;
extern NSString* NSRegistrationDomain;
/* Public notification */
extern NSString *NSUserDefaultsChanged;
/* Keys for language-dependent information */
extern NSString *NSWeekDayNameArray;
extern NSString *NSShortWeekDayNameArray;
extern NSString *NSMonthNameArray;
extern NSString *NSShortMonthNameArray;
extern NSString *NSTimeFormatString;
extern NSString *NSDateFormatString;
extern NSString *NSTimeDateFormatString;
extern NSString *NSShortTimeDateFormatString;
extern NSString *NSCurrencySymbol;
extern NSString *NSDecimalSeparator;
extern NSString *NSThousandsSeparator;
extern NSString *NSInternationalCurrencyString;
extern NSString *NSCurrencyString;
extern NSString *NSDecimalDigits;
extern NSString *NSAMPMDesignation;
/* NeXTSTEP 4.0 includes some more language-dependent constarnts:
extern NSString *NSHourNameDesignations;
extern NSString *NSYearMonthWeekDesignations;
extern NSString *NSEarlierTimeDesignations;
extern NSString *NSLaterTimeDesignations;
extern NSString *NSThisDayDesignations;
extern NSString *NSNextDayDesignations;
extern NSString *NSNextNextDayDesignations;
extern NSString *NSPriorDayDesignations;
extern NSString *NSDateTimeOrdering;
Perhaps one day they will be part of OpenStep and we should implement them.
*/
/* Get Information about a User */
#ifndef NEXT_FOUNDATION
extern NSString *NSUserName(void);
extern NSString *NSHomeDirectory(void);
extern NSString *NSHomeDirectoryForUser(NSString * userName);
#endif
/* General implementation notes:
OpenStep spec currently is either complete nor consitent. Therefor
we had to take several implementation decisions which make vary in
different OpenStep implementations.
- We add a new instance method initWithFile: as a designated
initialization method because it allows to create user defaults
database from a "default user" and also it will work for various
non-posix implementations.
- We add two new class methods for getting and setting a list of
user languages (userLanguages and setUserLanguages:). They are
somehow equivalent to the NS3.x Application's systemLanguages
method.
- Definition of argument (command line parameters)
(-GSxxxx || --GSxxx) [value]
Note: As far as I know, there is nothing like home directory for
the M$ hell. God help the Win95/WinNT users of NSUserDefaults ;-)
To Do:
- Add writeToFile: instance method;
- implement the description method;
- test for UNIX (write test app);
- ask somebody to test it for M$;
- polish & optimize;
- when tested, fix NSBundle (the system languages stuff);
- write docs :-(
*/
@interface NSUserDefaults: NSObject
{
@private
NSMutableArray *searchList; // Current search list;
NSMutableDictionary *persDomains; // Contains persistent defaults info;
NSMutableDictionary *tempDomains; // Contains volatile defaults info;
NSMutableArray *changedDomains; /* ..after first time that persistent
user defaults are changed */
BOOL tickingTimer; // for synchronization
}
/* Getting the Shared Instance */
+ (NSUserDefaults *)standardUserDefaults;
+ (NSArray *)userLanguages;
+ (void)setUserLanguages:(NSArray *)languages;
/* Initializing the User Defaults */
- (id)init;
- (id)initWithUser:(NSString *)userName;
- (id)initWithContentsOfFile:(NSString *)path; // This is a new method
/* Getting and Setting a Default */
- (NSArray *)arrayForKey:(NSString *)defaultName;
- (BOOL)boolForKey:(NSString *)defaultName;
- (NSData *)dataForKey:(NSString *)defaultName;
- (NSDictionary *)dictionaryForKey:(NSString *)defaultName;
- (float)floatForKey:(NSString *)defaultName;
- (int)integerForKey:(NSString *)defaultName;
- (id)objectForKey:(NSString *)defaultName;
- (void)removeObjectForKey:(NSString *)defaultName;
- (void)setBool:(BOOL)value forKey:(NSString *)defaultName;
- (void)setFloat:(float)value forKey:(NSString *)defaultName;
- (void)setInteger:(int)value forKey:(NSString *)defaultName;
- (void)setObject:(id)value forKey:(NSString *)defaultName;
- (NSArray *)stringArrayForKey:(NSString *)defaultName;
- (NSString *)stringForKey:(NSString *)defaultName;
/* Returning the Search List */
- (NSMutableArray *)searchList;
/* Maintaining Persistent Domains */
- (NSDictionary *)persistentDomainForName:(NSString *)domainName;
- (NSArray *)persistentDomainNames;
- (void)removePersistentDomainForName:(NSString *)domainName;
- (void)setPersistentDomain:(NSDictionary *)domain
forName:(NSString *)domainName;
- (BOOL)synchronize;
/* Maintaining Volatile Domains */
- (void)removeVolatileDomainForName:(NSString *)domainName;
- (void)setVolatileDomain:(NSDictionary *)domain
forName:(NSString *)domainName;
- (NSDictionary *)volatileDomainForName:(NSString *)domainName;
- (NSArray *)volatileDomainNames;
/* Making Advanced Use of Defaults */
- (NSDictionary *)dictionaryRepresentation;
- (void)registerDefaults:(NSDictionary *)dictionary;
@end
#endif /* __NSUserDefaults_h_OBJECTS_INCLUDE */

View file

@ -0,0 +1,28 @@
/* WIN32 extra config stuff */
//
// WIN32
//
#ifdef WIN32
# include <windows.h>
# ifndef vm_page_size
# define vm_page_size 4096
# endif
# define popen _popen
#endif
#define BITSPERBYTE 8
/* WIN32 extra config stuff */
//
// WIN32
//
#ifdef WIN32
# include <windows.h>
# ifndef vm_page_size
# define vm_page_size 4096
# endif
# define popen _popen
#endif

View file

@ -0,0 +1,4 @@
s/@NeXT_runtime@/0/
s/@NeXT_cc@/0/
s/@NeXT_runtime@/0/
s/@NeXT_cc@/0/

745
Source/NSUserDefaults.m Normal file
View file

@ -0,0 +1,745 @@
/* Implementation for NSUserDefaults for GNUStep
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Written by: Georg Tuparev, EMBL & Academia Naturalis,
Heidelberg, Germany
Tuparev@EMBL-Heidelberg.de
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gnustep/base/preface.h>
#if 0
/* My Linux doesn't have <libc.h>. Why is this necessary?
What is a work-around that will work for all? -mccallum*/
#include <libc.h>
/* If POSIX then: #include <unistd.h> */
#endif /* 0 */
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#ifdef NeXT
#include <foundation/NSUserDefaults.h>
#include <foundation/NSDictionary.h>
#include <foundation/NSArray.h>
#include <foundation/NSDate.h>
#include <foundation/NSUtilities.h>
#include <foundation/NSArchiver.h>
#include <foundation/NSException.h>
#include <foundation/NSNotification.h>
#include <foundation/NSTimer.h>
#include <foundation/NSProcessInfo.h>
#else
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSDate.h>
#include <Foundation/NSUtilities.h>
#include <Foundation/NSArchiver.h>
#include <Foundation/NSException.h>
#include <Foundation/NSNotification.h>
#include <Foundation/NSTimer.h>
#include <Foundation/NSProcessInfo.h>
#endif /* NeXT */
/* Wait for access */
#define _MAX_COUNT 5 /* Max 10 sec. */
/* User's Defauls database */
static NSString* GNU_UserDefaultsDatabese = @"./GNUStep/.GNUstepDefaults";
static NSString* GNU_UserDefaultsDatabeseLock = @"./GNUStep/.GNUstepUDLock";
/*************************************************************************
*** C O N S T A N T S
*************************************************************************/
/* Standard domains */
NSString* NSArgumentDomain = @"NSArgumentDomain";
NSString* NSGlobalDomain = @"NSGlobalDomain";
NSString* NSRegistrationDomain = @"NSRegistrationDomain";
/* Public notification */
NSString *NSUserDefaultsChanged = @"NSUserDefaultsChanged";
/* Keys for language-dependent information */
NSString *NSWeekDayNameArray = @"NSWeekDayNameArray";
NSString *NSShortWeekDayNameArray = @"NSShortWeekDayNameArray";
NSString *NSMonthNameArray = @"NSMonthNameArray";
NSString *NSShortMonthNameArray = @"NSShortMonthNameArray";
NSString *NSTimeFormatString = @"NSTimeFormatString";
NSString *NSDateFormatString = @"NSDateFormatString";
NSString *NSTimeDateFormatString = @"NSTimeDateFormatString";
NSString *NSShortTimeDateFormatString = @"NSShortTimeDateFormatString";
NSString *NSCurrencySymbol = @"NSCurrencySymbol";
NSString *NSDecimalSeparator = @"NSDecimalSeparator";
NSString *NSThousandsSeparator = @"NSThousandsSeparator";
NSString *NSInternationalCurrencyString = @"NSInternationalCurrencyString";
NSString *NSCurrencyString = @"NSCurrencyString";
NSString *NSDecimalDigits = @"NSDecimalDigits";
NSString *NSAMPMDesignation = @"NSAMPMDesignation";
/*************************************************************************
*** Get Information about a User
*************************************************************************/
#ifndef NeXT
// The functions used below showld work with /etc/passwd file,
// YP and NetInfo. I have no idea how this should be implemented
// for Win-NT and I know that this cannot be implemented fow Win95
NSString *NSUserName(void)
{
NSString* processOwner = [NSString stringWithCString: getlogin()];
return processOwner;
}
NSString *NSHomeDirectory(void)
{
return NSHomeDirectoryForUser (NSUserName());
}
NSString *NSHomeDirectoryForUser (NSString * userName)
{
struct passwd *pwd;
if (!userName)
return nil;
setpwent(); // Start scanning the password file
while ((pwd = getpwent ()))
{
if (strcmp(pwd->pw_name,[userName cString]) == 0)
break;
}
endpwent(); // Finish scanning the password file
if (!pwd)
return nil;
return [NSString stringWithCString:pwd->pw_dir];
}
#endif
/*************************************************************************
*** Local method definitions
*************************************************************************/
@interface NSUserDefaults (__local_NSUserDefaults)
- (void)__createStandardSearchList;
- (NSDictionary *)__createArgumentDictionary;
- (void)__changePersitentDomain:(NSString *)domainName;
@end
@implementation NSUserDefaults: NSObject
/*************************************************************************
*** Class variables
*************************************************************************/
static NSUserDefaults *sharedDefaults = nil;
static NSMutableString *defaultsDatabase = nil;
static NSMutableString *defaultsDatabaseLock = nil;
static NSMutableString *processName = nil;
/*************************************************************************
*** Getting the Shared Instance
*************************************************************************/
+ (NSUserDefaults *)standardUserDefaults
/*
Returns the shared defaults object. If it doesn't exist yet, it's
created. The defaults are initialized for the current user.
The search list is guaranteed to be standard only the first time
this method is invoked. The shared instance is provided as a
convenience; other instances may also be created.
*/
{
if (sharedDefaults)
return sharedDefaults;
// Create new sharedDefaults (NOTE: Not added to the autorelease pool!)
sharedDefaults = [[self alloc] init];
[sharedDefaults __createStandardSearchList];
return nil;
}
+ (NSArray *)userLanguages
{
NSMutableArray *uL = [NSMutableArray arrayWithCapacity:5];
NSArray *currLang = [[self standardUserDefaults]
stringArrayForKey:@"Languages"];
NSEnumerator *enumerator;
id obj;
if (!currLang)
{ // Try to build it from the env
const char *env_list;
NSString *env;
env_list = getenv("LANGUAGES");
if (env_list)
{
env = [NSString stringWithCString:env_list];
currLang = [[env componentsSeparatedByString:@";"] retain];
}
}
[uL addObjectsFromArray:currLang];
// Check if "English" is includet
enumerator = [uL objectEnumerator];
while ((obj = [enumerator nextObject]))
{
if ([obj isEqualToString:@"English"])
return uL;
}
[uL addObject:@"English"];
return uL;
}
+ (void)setUserLanguages:(NSArray *)languages
{
NSMutableDictionary *globDict = [[self standardUserDefaults]
persistentDomainForName:NSGlobalDomain];
if (!languages) // Remove the entry
[globDict removeObjectForKey:@"Languages"];
else
[globDict setObject:languages forKey:@"Languages"];
[[self standardUserDefaults]
setPersistentDomain:globDict forName:NSGlobalDomain];
return;
}
/*************************************************************************
*** Initializing the User Defaults
*************************************************************************/
- (id)init
/* Initializes defaults for current user calling initWithUser:. */
{
return [self initWithUser:NSUserName()];
}
- (id)initWithUser:(NSString *)userName
/* Initializes defaults for the specified user calling initWithFile:. */
{
NSMutableString* userHome = NSHomeDirectoryForUser(userName);
// Either userName is empty or it's wrong
if (!userHome)
{
[self release];
return nil;
}
[userHome appendString:GNU_UserDefaultsDatabese];
return [self initWithContentsOfFile:userHome];
}
- (id)initWithContentsOfFile:(NSString *)path
/* Initializes defaults for the specified path. Returns an object with
an empty search list. */
{
[super init];
// Find the user's home folder and build the paths (executed only once)
if (!defaultsDatabase)
{
defaultsDatabase =
[[NSMutableString stringWithFormat:@"%@/%@",
NSUserName(), GNU_UserDefaultsDatabese] retain];
defaultsDatabaseLock =
[[NSMutableString stringWithFormat:@"%@/%@",
NSUserName(), GNU_UserDefaultsDatabeseLock] retain];
processName = [[[NSProcessInfo processInfo] processName] retain];
#if 0
processName = [[NSMutableString stringWithFormat:@"TestApp"] retain];
#endif
}
// Create an empty search list
searchList = [[NSMutableArray arrayWithCapacity:10] retain];
// Initialize persDomains from the archived user defaults (persistent)
persDomains = [[NSMutableDictionary dictionaryWithCapacity:10] retain];
[self synchronize];
// Check and if not existent add the Application and the Global domains
if (![persDomains objectForKey:processName])
{
[persDomains setObject:
[NSMutableDictionary
dictionaryWithCapacity:10] forKey:processName];
[self __changePersitentDomain:processName];
}
if (![persDomains objectForKey:NSGlobalDomain])
{
[persDomains setObject:
[NSMutableDictionary
dictionaryWithCapacity:10] forKey:NSGlobalDomain];
[self __changePersitentDomain:NSGlobalDomain];
}
// Create volatile defaults and add the Argument and the Registration domains
tempDomains = [[NSMutableDictionary dictionaryWithCapacity:10] retain];
[tempDomains setObject:[self __createArgumentDictionary]
forKey:NSArgumentDomain];
[tempDomains setObject:
[NSMutableDictionary
dictionaryWithCapacity:10] forKey:NSRegistrationDomain];
return self;
}
- (void)dealloc
{
[searchList release];
[persDomains release];
[tempDomains release];
[changedDomains release];
[super dealloc];
}
- (NSString *)description
{
NSMutableString *desc =
[NSMutableString stringWithFormat:@"%@",[super description]];
// $$$ Not Implemented
// It's good idea to put all useful info here -- so I can test it later
[self notImplemented: _cmd];
return desc;
}
/*************************************************************************
*** Getting and Setting a Default
*************************************************************************/
- (NSArray *)arrayForKey:(NSString *)defaultName
{
id obj = [self objectForKey:defaultName];
if (obj && [obj isKindOfClass:[NSArray class]])
return obj;
return nil;
}
- (BOOL)boolForKey:(NSString *)defaultName
{
id obj = [self stringForKey:defaultName];
if (obj
&& ([obj isEqualToString:@"YES"] || [obj isEqualToString:@"yes"]
|| [obj intValue]))
return YES;
return NO;
}
- (NSData *)dataForKey:(NSString *)defaultName
{
id obj = [self objectForKey:defaultName];
if (obj && [obj isKindOfClass:[NSData class]])
return obj;
return nil;
}
- (NSDictionary *)dictionaryForKey:(NSString *)defaultName
{
id obj = [self objectForKey:defaultName];
if (obj && [obj isKindOfClass:[NSDictionary class]])
return obj;
return nil;
}
- (float)floatForKey:(NSString *)defaultName
{
id obj = [self stringForKey:defaultName];
if (obj)
return [obj floatValue];
return 0.0;
}
- (int)integerForKey:(NSString *)defaultName
{
id obj = [self stringForKey:defaultName];
if (obj)
return [obj intValue];
return 0;
}
- (id)objectForKey:(NSString *)defaultName
{
NSEnumerator *enumerator = [searchList objectEnumerator];
id object = nil;
id dN;
while ((dN = [enumerator nextObject]))
{
id dict;
dict = [persDomains objectForKey:dN];
if (dict && (object = [dict objectForKey:defaultName]))
break;
dict = [tempDomains objectForKey:dN];
if (dict && (object = [dict objectForKey:defaultName]))
break;
}
return object;
}
- (void)removeObjectForKey:(NSString *)defaultName
{
id obj = [[persDomains objectForKey:processName] objectForKey:defaultName];
if (obj)
{
[[persDomains objectForKey:processName] removeObjectForKey:defaultName];
[self __changePersitentDomain:processName];
}
return;
}
- (void)setBool:(BOOL)value forKey:(NSString *)defaultName
{
id obj = (value)?@"YES":@"NO";
[self setObject:obj forKey:defaultName];
return;
}
- (void)setFloat:(float)value forKey:(NSString *)defaultName
{
char buf[32];
sprintf(buf,"%g",value);
[self setObject:[NSString stringWithCString:buf] forKey:defaultName];
return;
}
- (void)setInteger:(int)value forKey:(NSString *)defaultName
{
char buf[32];
sprintf(buf,"%d",value);
[self setObject:[NSString stringWithCString:buf] forKey:defaultName];
return;
}
- (void)setObject:(id)value forKey:(NSString *)defaultName
{
if (value && defaultName && ([defaultName length] > 0))
{
[[persDomains objectForKey:processName]
setObject:value forKey:defaultName];
[self __changePersitentDomain:processName];
}
return;
}
- (NSArray *)stringArrayForKey:(NSString *)defaultName
{
id arr = [self arrayForKey:defaultName];
if (arr)
{
NSEnumerator *enumerator = [arr objectEnumerator];
id obj;
while ((obj = [enumerator nextObject]))
if ( ! [obj isKindOfClass:[NSString class]])
return nil;
return arr;
}
return nil;
}
- (NSString *)stringForKey:(NSString *)defaultName
{
id obj = [self objectForKey:defaultName];
if (obj && [obj isKindOfClass:[NSString class]])
return obj;
return nil;
}
/*************************************************************************
*** Returning the Search List
*************************************************************************/
- (NSMutableArray *)searchList
{
return searchList;
}
/*************************************************************************
*** Maintaining Persistent Domains
*************************************************************************/
- (NSDictionary *)persistentDomainForName:(NSString *)domainName
{
return [persDomains objectForKey:domainName];
}
- (NSArray *)persistentDomainNames
{
return [persDomains allKeys];
}
- (void)removePersistentDomainForName:(NSString *)domainName
{
if ([persDomains objectForKey:domainName])
{
[persDomains removeObjectForKey:domainName];
[self __changePersitentDomain:domainName];
}
return;
}
- (void)setPersistentDomain:(NSDictionary *)domain
forName:(NSString *)domainName
{
id dict = [tempDomains objectForKey:domainName];
if (dict)
{
[NSException raise:NSInvalidArgumentException
format:@"Volatile domain with %@ already exists",
domainName];
return;
}
[persDomains setObject:domain forKey:domainName];
[self __changePersitentDomain:domainName];
return;
}
- (BOOL)synchronize
{
NSMutableDictionary *newDict = nil;
tickingTimer = NO;
// Get file lock
if (mkdir([defaultsDatabase cString],0755) == -1)
return NO;
// Read the persistent data from the stored database
newDict = [[NSMutableDictionary allocWithZone:[self zone]]
initWithContentsOfFile:defaultsDatabase];
if (!newDict)
{
rmdir([defaultsDatabaseLock cString]); // release file lock
return NO;
}
if (changedDomains)
{ // Synchronize bpth dictionaries
NSEnumerator *enumerator = [changedDomains objectEnumerator];
id obj, dict;
while ((obj = [enumerator nextObject]))
{
dict = [persDomains objectForKey:obj];
if (dict) // Domane was added or changet
[newDict setObject:dict forKey:obj];
else // Domain was removed
[newDict removeObjectForKey:obj];
}
[persDomains release];
persDomains = newDict;
// Save the changes
if (![persDomains writeToFile:defaultsDatabase atomically:YES])
{
rmdir([defaultsDatabaseLock cString]); // release file lock
return NO;
}
}
else
{ // Just update from disk
[persDomains release];
persDomains = newDict;
}
rmdir([defaultsDatabaseLock cString]); // release file lock
return YES;
}
/*************************************************************************
*** Maintaining Volatile Domains
*************************************************************************/
- (void)removeVolatileDomainForName:(NSString *)domainName
{
[tempDomains removeObjectForKey:domainName];
return;
}
- (void)setVolatileDomain:(NSDictionary *)domain
forName:(NSString *)domainName
{
id dict = [persDomains objectForKey:domainName];
if (dict)
{
[NSException raise:NSInvalidArgumentException
format:@"Persistent domain with %@ already exists",
domainName];
return;
}
[tempDomains setObject:domain forKey:domainName];
return;
}
- (NSDictionary *)volatileDomainForName:(NSString *)domainName
{
return [tempDomains objectForKey:domainName];
}
- (NSArray *)volatileDomainNames
{
return [tempDomains allKeys];
}
/*************************************************************************
*** Making Advanced Use of Defaults
*************************************************************************/
- (NSDictionary *)dictionaryRepresentation
{
NSEnumerator *enumerator = [searchList reverseObjectEnumerator];
NSMutableDictionary *dictRep =
[NSMutableDictionary dictionaryWithCapacity:10];
id obj;
id dict;
while ((obj = [enumerator nextObject]))
{
if ( (dict = [persDomains objectForKey:obj])
|| (dict = [tempDomains objectForKey:obj]) )
[dictRep addEntriesFromDictionary:dict];
}
// $$$ Should we return NSDictionary here ?
return dictRep;
}
- (void)registerDefaults:(NSDictionary *)dictionary
{
[tempDomains setObject:dictionary forKey:NSRegistrationDomain];
return;
}
/*************************************************************************
*** Accessing the User Defaults database
*************************************************************************/
- (void)__createStandardSearchList
{
NSArray *uL = [[self class] userLanguages];
NSEnumerator *enumerator = [uL objectEnumerator];
id object;
// Note: The search list should exist!
// 1. NSArgumentDomain
[searchList addObject:NSArgumentDomain];
// 2. Application
[searchList addObject:processName];
// 3. User's preferred languages
while ((object = [enumerator nextObject]))
{
[searchList addObject:object];
}
// 4. NSGlobalDomain
[searchList addObject:NSGlobalDomain];
// 5. NSRegistrationDomain
[searchList addObject:NSRegistrationDomain];
return;
}
- (NSDictionary *)__createArgumentDictionary
{
NSArray *args = [[NSProcessInfo processInfo] arguments];
//$$$ NSArray *args = searchList; // $$$
NSEnumerator *enumerator = [args objectEnumerator];
NSMutableDictionary *argDict =
[NSMutableDictionary dictionaryWithCapacity:2];
BOOL done;
id key, val;
done = ((key = [enumerator nextObject]) == nil);
while (!done)
{
if ([key hasPrefix:@"-GS"] || [key hasPrefix:@"--GS"]) {
val = [enumerator nextObject];
if (!val)
{ // No more args
[argDict setObject:nil forKey:key];
done = YES;
continue;
}
else if ([val hasPrefix:@"-"])
{ // Yet another argument
[argDict setObject:nil forKey:key];
key = val;
continue;
}
else
{ // Real parameter
[argDict setObject:val forKey:key];
}
}
done = ((key = [enumerator nextObject]) == nil);
}
return argDict;
}
- (void)__changePersitentDomain:(NSString *)domainName
{
NSEnumerator *enumerator = nil;
id obj;
if (!changedDomains)
{
changedDomains = [[NSMutableArray arrayWithCapacity:5] retain];
[[NSNotificationCenter defaultCenter]
postNotificationName:NSUserDefaultsChanged object:nil];
}
if (!tickingTimer)
{
[NSTimer scheduledTimerWithTimeInterval:30
target:self
selector:@selector(synchronize)
userInfo:nil
repeats:NO];
tickingTimer = YES;
}
enumerator = [changedDomains objectEnumerator];
while ((obj = [enumerator nextObject]))
{
if ([obj isEqualToString:domainName])
return;
}
[changedDomains addObject:domainName];
return;
}
@end

143
Testing/release.m Normal file
View file

@ -0,0 +1,143 @@
#include <Foundation/NSObject.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSAutoreleasePool.h>
#include "malloc.h"
@interface ReleaseTester : NSObject
{
int label;
}
@end
@implementation ReleaseTester
- initWithLabel: (int)l
{
label = l;
return self;
}
- (oneway void) release
{
// printf ("release'ing %d\n", label);
[super release];
}
- (void) dealloc
{
// printf ("dealloc'ing %d\n", label);
[super dealloc];
}
@end
void
autorelease_test (int depth)
{
int n = 2;
id os[n];
id a = [NSArray new];
int i;
id arp;
if (depth < 0)
return;
arp = [[NSAutoreleasePool alloc] init];
for (i = 0; i < n; i++)
{
id r = [[[ReleaseTester alloc] initWithLabel: i+depth*n] autorelease];
os[i] = r;
[a addObject: r];
}
#if 0
fprintf (stderr, "totalAutoreleasedObjects %d\n",
[NSAutoreleasePool totalAutoreleasedObjects]);
#endif
autorelease_test (depth-1);
[a release];
[arp release];
fflush (stdin);
}
void
release_test (int depth)
{
int n = 1000;
id os[n];
int i;
if (depth < 0)
return;
for (i = 0; i < n; i++)
os[i] = [[ReleaseTester alloc] initWithLabel: i];
for (i = 0; i < n; i++)
[os[i] retain];
for (i = 0; i < n; i++)
[os[i] release];
for (i = 0; i < n; i++)
[os[i] release];
release_test (depth-1);
}
#if GNU_LIBC
static void *(*old_malloc_hook) (size_t);
static void (*old_free_hook) (void *ptr);
static void *
my_malloc_hook (size_t size)
{
void *result;
__malloc_hook = old_malloc_hook;
result = malloc (size);
/* `printf' might call `malloc', so protect it too. */
printf ("malloc (%u) returns %p\n", (unsigned int) size, result);
__malloc_hook = my_malloc_hook;
return result;
}
void
my_free_hook (void *ptr)
{
__free_hook = old_free_hook;
free (ptr);
__free_hook = my_free_hook;
}
#endif /* GNU_LIBC */
int
main ()
{
int i;
#if GNU_LIBC
old_malloc_hook = __malloc_hook;
old_free_hook = __free_hook;
__malloc_hook = my_malloc_hook;
__free_hook = my_free_hook;
#endif /* GNU_LIBC */
#if 1
for (i = 0; i < 10000; i++)
autorelease_test (3);
#else
/* Checking for memory leak in objc_mutex_lock() */
_objc_mutex_t gate;
gate = objc_mutex_allocate ();
for (i = 0; i < 1000000; i++)
{
objc_mutex_lock (gate);
objc_mutex_unlock (gate);
}
#endif
exit (0);
}