Tidyup categories

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@16478 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2003-04-17 06:20:17 +00:00
parent e9733d43d2
commit 917cd26e5d
14 changed files with 161 additions and 53 deletions

View file

@ -1,3 +1,25 @@
2003-04-17 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/gnustep/base/GSCategories.h:
* Headers/gnustep/base/NSCalendarDate.h:
* Headers/gnustep/base/NSData.h:
* Headers/gnustep/base/NSObject.h:
* Headers/gnustep/base/NSString.h:
* Headers/gnustep/base/NSValue.h:
* Headers/gnustep/base/Foundation.h:
Tidied use of GSCategories.
2003-04-16 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/gnustep/base/NSUserDefaults.h: remove timer ivar, now unused.
* Source/NSRunLoop.m: Support a housekeeping timer which is ignored
for purposes of deciding whether the loop shoiuld terminate.
* Source/NSThread.m: Set up housekeeping timer to trigger housekeeping
notifications in the default mode of the runloop of the main thread.
* Source/NSUserDefaults.m: Use housekeeping notifications to trigger
synchronise rather than using timers ... avoid circular dependencies.
Thanks to Derek Zhou for bug report.
2003-04-15 Richard Frith-Macdonald <rfm@gnu.org> 2003-04-15 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSData.m: Experimantal disable ReadFile and WriteFile on MINGW * Source/NSData.m: Experimantal disable ReadFile and WriteFile on MINGW

View file

@ -90,7 +90,5 @@
#include <Foundation/NSUserDefaults.h> #include <Foundation/NSUserDefaults.h>
#include <Foundation/NSValue.h> #include <Foundation/NSValue.h>
#include <Foundation/NSZone.h> #include <Foundation/NSZone.h>
#include <gnustep/base/GSCategories.h>
#include <gnustep/base/GSObjCRuntime.h>
#endif /* __Foundation_h_GNUSTEP_BASE_INCLUDE */ #endif /* __Foundation_h_GNUSTEP_BASE_INCLUDE */

View file

@ -26,29 +26,26 @@
*/ */
#ifndef NO_GNUSTEP
#ifndef NeXT_Foundation_LIBRARY /* The following ifndef prevents the categories declared in this file being
#include <Foundation/NSCalendarDate.h> * seen in GNUstep code. This is necessary because those category
#include <Foundation/NSData.h> * declarations are also present in the header files for the corresponding
#include <Foundation/NSString.h> * classes in GNUstep. The separate category declarations in this file
#include <Foundation/NSValue.h> * are only needed for software using the GNUstep Additions library
#else * without the main GNUstep base library.
*/
#ifndef GNUSTEP
#include <Foundation/Foundation.h> #include <Foundation/Foundation.h>
#endif
@interface NSCalendarDate (GSCategories) @interface NSCalendarDate (GSCategories)
- (int) weekOfYear; - (int) weekOfYear;
@end @end
@interface NSData (GSCategories) @interface NSData (GSCategories)
- (NSString*) hexadecimalRepresentation; - (NSString*) hexadecimalRepresentation;
- (id) initWithHexadecimalRepresentation: (NSString*)string; - (id) initWithHexadecimalRepresentation: (NSString*)string;
- (NSData*) md5Digest; - (NSData*) md5Digest;
@end @end
@interface NSString (GSCategories) @interface NSString (GSCategories)
@ -75,19 +72,17 @@
+ (NSValue*) valueFromString: (NSString *)string; + (NSValue*) valueFromString: (NSString *)string;
@end @end
/* This is also defined in NSObject.h, but added here for use with the
additions library */
#ifndef NSOBJECT_GSCATEGORIES_INTERFACE
@interface NSObject (GSCategories) @interface NSObject (GSCategories)
- notImplemented:(SEL)aSel; - notImplemented:(SEL)aSel;
- (id) subclassResponsibility: (SEL)aSel; - (id) subclassResponsibility: (SEL)aSel;
- (id) shouldNotImplement: (SEL)aSel; - (id) shouldNotImplement: (SEL)aSel;
- (NSComparisonResult) compare: (id)anObject; - (NSComparisonResult) compare: (id)anObject;
@end @end
#endif
#endif /* GNUSTEP */
#ifndef GS_MAX_OBJECTS_FROM_STACK #ifndef GS_MAX_OBJECTS_FROM_STACK
/** /**
@ -235,5 +230,4 @@
}) })
#endif /* NO_GNUSTEP */
#endif /* INCLUDED_GS_CATEGORIES_H */ #endif /* INCLUDED_GS_CATEGORIES_H */

View file

@ -105,6 +105,11 @@
@end @end
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP
@interface NSCalendarDate (GSCategories)
- (int) weekOfYear;
@end
@interface NSCalendarDate (GregorianDate) @interface NSCalendarDate (GregorianDate)
- (int) lastDayOfGregorianMonth: (int)month year: (int)year; - (int) lastDayOfGregorianMonth: (int)month year: (int)year;

View file

@ -116,6 +116,12 @@
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP
@interface NSData (GSCategories)
- (NSString*) hexadecimalRepresentation;
- (id) initWithHexadecimalRepresentation: (NSString*)string;
- (NSData*) md5Digest;
@end
/* /*
* We include special support for coding/decoding - adding methods for * We include special support for coding/decoding - adding methods for
* serializing/deserializing type-tags and cross-references. * serializing/deserializing type-tags and cross-references.
@ -250,6 +256,7 @@
@end @end
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP
@interface NSMutableData (GNUstepExtensions) @interface NSMutableData (GNUstepExtensions)
/* /*
* Capacity management - GNUstep gives you control over the size of * Capacity management - GNUstep gives you control over the size of

View file

@ -291,12 +291,10 @@ GS_EXPORT NSRecursiveLock *gnustep_global_lock;
- (id) write: (TypedStream*)aStream; - (id) write: (TypedStream*)aStream;
@end @end
#define NSOBJECT_GSCATEGORIES_INTERFACE
@interface NSObject (GSCategories) @interface NSObject (GSCategories)
- notImplemented:(SEL)aSel; - notImplemented:(SEL)aSel;
- (id) subclassResponsibility: (SEL)aSel; - (id) subclassResponsibility: (SEL)aSel;
- (id) shouldNotImplement: (SEL)aSel; - (id) shouldNotImplement: (SEL)aSel;
- (NSComparisonResult) compare: (id)anObject; - (NSComparisonResult) compare: (id)anObject;
@end @end

View file

@ -369,6 +369,27 @@ extern struct objc_class _NSConstantStringClassReference;
@interface NSMutableString (GNUstep) @interface NSMutableString (GNUstep)
- (NSString*) immutableProxy; - (NSString*) immutableProxy;
@end @end
@interface NSString (GSCategories)
- (NSString*) stringByDeletingPrefix: (NSString*)prefix;
- (NSString*) stringByDeletingSuffix: (NSString*)suffix;
- (NSString*) stringByTrimmingLeadSpaces;
- (NSString*) stringByTrimmingTailSpaces;
- (NSString*) stringByTrimmingSpaces;
- (NSString*) stringByReplacingString: (NSString*)replace
withString: (NSString*)by;
@end
@interface NSMutableString (GSCategories)
- (void) deleteSuffix: (NSString*)suffix;
- (void) deletePrefix: (NSString*)prefix;
- (void) replaceString: (NSString*)replace
withString: (NSString*)by;
- (void) trimLeadSpaces;
- (void) trimTailSpaces;
- (void) trimSpaces;
@end
#endif /* NO_GNUSTEP */ #endif /* NO_GNUSTEP */
#endif /* __NSString_h_GNUSTEP_BASE_INCLUDE */ #endif /* __NSString_h_GNUSTEP_BASE_INCLUDE */

View file

@ -107,7 +107,6 @@ GS_EXPORT NSString* const NSLocale;
the M$ hell. God help the Win95/WinNT users of NSUserDefaults ;-) the M$ hell. God help the Win95/WinNT users of NSUserDefaults ;-)
To Do: To Do:
- ask somebody to test it for M$;
- polish & optimize; - polish & optimize;
- when tested, fix NSBundle (the system languages stuff); - when tested, fix NSBundle (the system languages stuff);
- write docs : -( - write docs : -(
@ -124,7 +123,6 @@ GS_EXPORT NSString* const NSLocale;
NSDictionary *_dictionaryRep; // Cached dictionary representation NSDictionary *_dictionaryRep; // Cached dictionary representation
NSString *_defaultsDatabase; NSString *_defaultsDatabase;
NSDate *_lastSync; NSDate *_lastSync;
NSTimer *_tickingTimer; // for synchronization
NSRecursiveLock *_lock; NSRecursiveLock *_lock;
NSDistributedLock *_fileLock; NSDistributedLock *_fileLock;
} }
@ -168,7 +166,7 @@ GS_EXPORT NSString* const NSLocale;
/* Returning the Search List */ /* Returning the Search List */
- (NSMutableArray*) searchList; - (NSMutableArray*) searchList;
- (void)setSearchList: (NSArray*)newList; - (void) setSearchList: (NSArray*)newList;
/* Maintaining Persistent Domains */ /* Maintaining Persistent Domains */
- (NSDictionary*) persistentDomainForName: (NSString*)domainName; - (NSDictionary*) persistentDomainForName: (NSString*)domainName;

View file

@ -118,6 +118,11 @@
@end @end
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP
@interface NSNumber(GSCategories)
+ (NSValue*) valueFromString: (NSString *)string;
@end
/* Note: This method is not in the OpenStep spec, but they makes /* Note: This method is not in the OpenStep spec, but they makes
subclassing easier. */ subclassing easier. */
@interface NSValue (Subclassing) @interface NSValue (Subclassing)

View file

@ -176,6 +176,8 @@ _arg_addr(NSInvocation *inv, int index)
/** /**
* Returns an invocation instance which can be used to send messages to * Returns an invocation instance which can be used to send messages to
* a target object using the described signature.<br /> * a target object using the described signature.<br />
* You must set the target and selector (using -setTarget: and -setSelector:)
* before you attempt to use the invocation.<br />
* Raises an NSInvalidArgumentException if the signature is nil. * Raises an NSInvalidArgumentException if the signature is nil.
*/ */
+ (NSInvocation*) invocationWithMethodSignature: (NSMethodSignature*)_signature + (NSInvocation*) invocationWithMethodSignature: (NSMethodSignature*)_signature
@ -734,6 +736,8 @@ _arg_addr(NSInvocation *inv, int index)
/** <init /><override-subclass /> /** <init /><override-subclass />
* Initialised an invocation instance which can be used to send messages to * Initialised an invocation instance which can be used to send messages to
* a target object using aSignature.<br /> * a target object using aSignature.<br />
* You must set the target and selector (using -setTarget: and -setSelector:)
* before you attempt to use the invocation.<br />
* Raises an NSInvalidArgumentException if aSignature is nil. * Raises an NSInvalidArgumentException if aSignature is nil.
*/ */
- (id) initWithMethodSignature: (NSMethodSignature*)aSignature - (id) initWithMethodSignature: (NSMethodSignature*)aSignature

View file

@ -604,7 +604,6 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
info = GSIArrayItemAtIndex(watchers, i).obj; info = GSIArrayItemAtIndex(watchers, i).obj;
if (info->_invalidated == YES) if (info->_invalidated == YES)
{ {
GSIArrayRemoveItemAtIndex(watchers, i);
continue; continue;
} }
@ -1622,7 +1621,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
+ (NSRunLoop*) currentRunLoop + (NSRunLoop*) currentRunLoop
{ {
extern NSRunLoop *GSRunLoopForThread(); extern NSRunLoop *GSRunLoopForThread();
return GSRunLoopForThread(nil); return GSRunLoopForThread(nil);
} }
@ -1709,6 +1708,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
*/ */
- (NSDate*) limitDateForMode: (NSString*)mode - (NSDate*) limitDateForMode: (NSString*)mode
{ {
extern NSTimer *GSHousekeeper();
GSRunLoopCtxt *context = NSMapGet(_contextMap, mode); GSRunLoopCtxt *context = NSMapGet(_contextMap, mode);
NSDate *when = nil; NSDate *when = nil;
@ -1825,6 +1825,32 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
min_watcher = nil; min_watcher = nil;
} }
} }
/*
* If there is nothing being watched, and no valid timers
* other than the housekeeper, we set min_timer to nil so
* that the housekeeper timer does not keep the runloop
* active. It's a special case set up in NSThread.m
*/
if (min_watcher == nil && min_timer != nil
&& min_timer == GSHousekeeper())
{
unsigned count = GSIArrayCount(timers);
while (count-- > 1)
{
NSTimer *tmp = GSIArrayItemAtIndex(timers, 0).obj;
if (timerInvalidated(tmp) == YES)
{
GSIArrayRemoveItemAtIndex(timers, count);
}
}
if (GSIArrayCount(timers) == 1)
{
min_timer = nil;
}
}
_currentMode = savedMode; _currentMode = savedMode;
} }
NS_HANDLER NS_HANDLER

View file

@ -42,6 +42,7 @@
#include <Foundation/NSNotificationQueue.h> #include <Foundation/NSNotificationQueue.h>
#include <Foundation/NSRunLoop.h> #include <Foundation/NSRunLoop.h>
#include <Foundation/NSConnection.h> #include <Foundation/NSConnection.h>
#include <Foundation/NSInvocation.h>
@class GSPerformHolder; @class GSPerformHolder;
@ -197,6 +198,22 @@ GSCurrentThreadDictionary()
return GSDictionaryForThread(nil); return GSDictionaryForThread(nil);
} }
/*
* The special timer which we set up in the run loop of the main thread
* to perform housekeeping duties. NSRunLoop needs to call this private
* function so it knows about the housekeeping timer and won't keep the
* loop running just to do housekeeping.
*
* The NSUserDefaults system registers as an observer of GSHousekeeping
* notifications in order to synchronise the in-memory cache and the
* on-disk database.
*/
static NSTimer *housekeeper = nil;
NSTimer *GSHousekeeper()
{
return housekeeper;
}
/** /**
* Returns the runloop for the specified thread (or, if t is nil, * Returns the runloop for the specified thread (or, if t is nil,
* for the current thread). Creates a new runloop if necessary.<br /> * for the current thread). Creates a new runloop if necessary.<br />
@ -217,6 +234,30 @@ GSRunLoopForThread(NSThread *t)
r = [NSRunLoop new]; r = [NSRunLoop new];
[d setObject: r forKey: key]; [d setObject: r forKey: key];
RELEASE(r); RELEASE(r);
if (t == nil || t == defaultThread)
{
NSNotificationCenter *ctr;
NSNotification *not;
NSInvocation *inv;
SEL sel;
ctr = [NSNotificationCenter defaultCenter];
not = [NSNotification notificationWithName: @"GSHousekeeping"
object: r
userInfo: nil];
sel = @selector(postNotification:);
inv = [NSInvocation invocationWithMethodSignature:
[ctr methodSignatureForSelector: sel]];
[inv setTarget: ctr];
[inv setSelector: sel];
[inv setArgument: &not atIndex: 2];
[inv retainArguments];
housekeeper = [NSTimer timerWithTimeInterval: 30.0
invocation: inv
repeats: YES];
[r addTimer: housekeeper forMode: NSDefaultRunLoopMode];
}
} }
} }
return r; return r;

View file

@ -92,7 +92,7 @@ static Class NSDate_class;
} }
/** /**
* Create a timer wchich will fire after ti seconds and, if f is YES, * Create a timer which will fire after ti seconds and, if f is YES,
* every ti seconds thereafter. On firing, invocation will be performed.<br /> * every ti seconds thereafter. On firing, invocation will be performed.<br />
* NB. To make the timer operate, you must add it to a run loop. * NB. To make the timer operate, you must add it to a run loop.
*/ */
@ -111,7 +111,7 @@ static Class NSDate_class;
/** /**
* Create a timer wchich will fire after ti seconds and, if f is YES, * Create a timer wchich will fire after ti seconds and, if f is YES,
* every ti seconds thereafter. On firing, the target object will be * every ti seconds thereafter. On firing, the target object will be
* sent a message specified by selector and with the object info as an * sent a message specified by selector and with the value info as an
* argument.<br /> * argument.<br />
* NB. To make the timer operate, you must add it to a run loop. * NB. To make the timer operate, you must add it to a run loop.
*/ */

View file

@ -130,7 +130,6 @@ static void updateCache(NSUserDefaults *self)
- (void) __createStandardSearchList; - (void) __createStandardSearchList;
- (NSDictionary*) __createArgumentDictionary; - (NSDictionary*) __createArgumentDictionary;
- (void) __changePersistentDomain: (NSString*)domainName; - (void) __changePersistentDomain: (NSString*)domainName;
- (void) __timerTicked: (NSTimer*)tim;
@end @end
/** /**
@ -522,7 +521,8 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
[tempDefaults setSearchList: sList]; [tempDefaults setSearchList: sList];
RELEASE(sList); RELEASE(sList);
currLang = [tempDefaults stringArrayForKey: @"NSLanguages"]; currLang = [tempDefaults stringArrayForKey: @"NSLanguages"];
AUTORELEASE(tempDefaults); AUTORELEASE(RETAIN(currLang));
RELEASE(tempDefaults);
} }
} }
else else
@ -825,15 +825,17 @@ static NSString *pathForUser(NSString *user)
setObject: [NSMutableDictionaryClass dictionaryWithCapacity: 10] setObject: [NSMutableDictionaryClass dictionaryWithCapacity: 10]
forKey: NSRegistrationDomain]; forKey: NSRegistrationDomain];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(synchronize)
name: @"GSHousekeeping"
object: nil];
return self; return self;
} }
- (void) dealloc - (void) dealloc
{ {
if (_tickingTimer != nil) [[NSNotificationCenter defaultCenter] removeObserver: self];
{
[_tickingTimer invalidate];
}
RELEASE(_lastSync); RELEASE(_lastSync);
RELEASE(_searchList); RELEASE(_searchList);
RELEASE(_persDomains); RELEASE(_persDomains);
@ -1364,15 +1366,6 @@ static BOOL isPlistObject(id o)
} }
} }
if (_tickingTimer == nil)
{
_tickingTimer = [NSTimer scheduledTimerWithTimeInterval: 30
target: self
selector: @selector(__timerTicked:)
userInfo: nil
repeats: NO];
}
/* /*
* If we haven't changed anything, we only need to synchronise if * If we haven't changed anything, we only need to synchronise if
* the on-disk database has been changed by someone else. * the on-disk database has been changed by someone else.
@ -1397,8 +1390,12 @@ static BOOL isPlistObject(id o)
{ {
NSDate *mod; NSDate *mod;
/*
* If the database was modified since the last synchronisation
* we need to read it.
*/
mod = [attr objectForKey: NSFileModificationDate]; mod = [attr objectForKey: NSFileModificationDate];
if (mod !=nil && [_lastSync earlierDate: mod] != _lastSync) if (mod != nil && [_lastSync laterDate: mod] != _lastSync)
{ {
wantRead = YES; wantRead = YES;
} }
@ -1806,14 +1803,6 @@ static BOOL isPlistObject(id o)
} }
[_lock unlock]; [_lock unlock];
} }
- (void) __timerTicked: (NSTimer*)tim
{
if (tim == _tickingTimer)
_tickingTimer = nil;
[self synchronize];
}
@end @end
NSDictionary* NSDictionary*