mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Masses of fixes
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@5474 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
f2ba659be3
commit
d1334aab5b
8 changed files with 666 additions and 483 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
|||
Mon Dec 13 12:20:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
|
||||
Fixes for cball's changes (who is cball?, and why didn't s/he produce
|
||||
a ChangeLog entry or conform to GNU indentation? It took me hours to
|
||||
tidy this up).
|
||||
* Source/NSDate.m: ([NSGDate -addTimeInterval:]) removed bogus
|
||||
implementation of method (inherits from NSDate).
|
||||
* Source/NSCalendarDate.m: Added implementation of ([-addTimeInterval:])
|
||||
with specific code for NSCalendarDate. Reformatted code to GNUstep
|
||||
style.
|
||||
* Source/NSGArray.m: ([-removeObjectIdenticalTo:]) and
|
||||
([-removeObjectIdenticalTo:inRange:]) reverted to correct code.
|
||||
([-removeObject:]) and ([-removeObjectIdenticalTo:inRange:]) removed
|
||||
changes and added fixes so that methods are safe where multiple objects
|
||||
equal to the object to be removed are present in the array.
|
||||
* Source/NSArray.m: Similar fixes for object removal.
|
||||
* Source/NSObject.m: Rewritten mutex code so that mutexes are not used
|
||||
for retain/release unless the app is multi-threaded.
|
||||
|
||||
Wed Dec 1 19:36:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
|
||||
* Source/NSArray.m: When sorting, treat illegal return values from the
|
||||
|
|
|
@ -898,13 +898,10 @@ static NSString *indentStrings[] = {
|
|||
if (o == anObject)
|
||||
{
|
||||
if (rem == 0)
|
||||
rem = [self methodForSelector: remSel];
|
||||
{
|
||||
rem = [self methodForSelector: remSel];
|
||||
}
|
||||
(*rem)(self, remSel, i);
|
||||
/*
|
||||
* Bail out now or run the risk of comparing against a garbage
|
||||
* pointer.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -942,15 +939,24 @@ static NSString *indentStrings[] = {
|
|||
if (o == anObject || (*eq)(anObject, eqSel, o) == YES)
|
||||
{
|
||||
if (rem == 0)
|
||||
rem = [self methodForSelector: remSel];
|
||||
{
|
||||
rem = [self methodForSelector: remSel];
|
||||
/*
|
||||
* We need to retain the object so that when we remove the
|
||||
* first equal object we don't get left with a bad object
|
||||
* pointer for later comparisons.
|
||||
*/
|
||||
RETAIN(anObject);
|
||||
}
|
||||
(*rem)(self, remSel, i);
|
||||
/*
|
||||
* Bail out now or run the risk of comparing against a garbage
|
||||
* pointer.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifndef GS_WITH_GC
|
||||
if (rem != 0)
|
||||
{
|
||||
RELEASE(anObject);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -984,13 +990,10 @@ static NSString *indentStrings[] = {
|
|||
if (o == anObject)
|
||||
{
|
||||
if (rem == 0)
|
||||
rem = [self methodForSelector: remSel];
|
||||
{
|
||||
rem = [self methodForSelector: remSel];
|
||||
}
|
||||
(*rem)(self, remSel, i);
|
||||
/*
|
||||
* Bail out now or run the risk of comparing against a garbage
|
||||
* pointer.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1020,15 +1023,24 @@ static NSString *indentStrings[] = {
|
|||
if (o == anObject || (*eq)(anObject, eqSel, o) == YES)
|
||||
{
|
||||
if (rem == 0)
|
||||
rem = [self methodForSelector: remSel];
|
||||
{
|
||||
rem = [self methodForSelector: remSel];
|
||||
/*
|
||||
* We need to retain the object so that when we remove the
|
||||
* first equal object we don't get left with a bad object
|
||||
* pointer for later comparisons.
|
||||
*/
|
||||
RETAIN(anObject);
|
||||
}
|
||||
(*rem)(self, remSel, i);
|
||||
/*
|
||||
* Bail out now or run the risk of comparing against a garbage
|
||||
* pointer.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifndef GS_WITH_GC
|
||||
if (rem != 0)
|
||||
{
|
||||
RELEASE(anObject);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1041,7 +1053,9 @@ static NSString *indentStrings[] = {
|
|||
IMP remLast = [self methodForSelector: rlSel];
|
||||
|
||||
while (c--)
|
||||
(*remLast)(self, rlSel);
|
||||
{
|
||||
(*remLast)(self, rlSel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1149,7 +1163,9 @@ static NSString *indentStrings[] = {
|
|||
IMP rem = [self methodForSelector: remSel];
|
||||
|
||||
while (i-- > s)
|
||||
(*rem)(self, remSel, i);
|
||||
{
|
||||
(*rem)(self, remSel, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,16 @@
|
|||
return AUTORELEASE(d);
|
||||
}
|
||||
|
||||
- (id) addTimeInterval: (NSTimeInterval)seconds
|
||||
{
|
||||
id newObj = [[self class] dateWithTimeIntervalSinceReferenceDate:
|
||||
[self timeIntervalSinceReferenceDate] + seconds];
|
||||
|
||||
[newObj setTimeZone: [self timeZoneDetail]];
|
||||
|
||||
return newObj;
|
||||
}
|
||||
|
||||
- (Class) classForPortCoder
|
||||
{
|
||||
return [self class];
|
||||
|
@ -129,14 +139,16 @@
|
|||
|
||||
- (void) encodeWithCoder: (NSCoder*)coder
|
||||
{
|
||||
[coder encodeValueOfObjCType: @encode(NSTimeInterval) at: &_seconds_since_ref];
|
||||
[coder encodeValueOfObjCType: @encode(NSTimeInterval)
|
||||
at: &_seconds_since_ref];
|
||||
[coder encodeObject: _calendar_format];
|
||||
[coder encodeObject: _time_zone];
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
[coder decodeValueOfObjCType: @encode(NSTimeInterval) at: &_seconds_since_ref];
|
||||
[coder decodeValueOfObjCType: @encode(NSTimeInterval)
|
||||
at: &_seconds_since_ref];
|
||||
[coder decodeValueOfObjCType: @encode(id) at: &_calendar_format];
|
||||
[coder decodeValueOfObjCType: @encode(id) at: &_time_zone];
|
||||
return self;
|
||||
|
@ -174,32 +186,29 @@
|
|||
calendarFormat: (NSString *)fmt
|
||||
locale: (NSDictionary *)locale
|
||||
{
|
||||
int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0;
|
||||
NSTimeZone *tz = [NSTimeZone localTimeZone];
|
||||
|
||||
int ampm = 0, twelveHrClock = 0;
|
||||
int julianWeeks = -1, weekStartsMonday = 0, dayOfWeek = -1;
|
||||
|
||||
const char *source = [description cString];
|
||||
int sourceLen = strlen(source);
|
||||
const char *format = [fmt cString];
|
||||
int formatLen = strlen(format);
|
||||
|
||||
int formatIdx = 0;
|
||||
int sourceIdx = 0;
|
||||
|
||||
char tmpStr[20];
|
||||
int tmpIdx;
|
||||
int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0;
|
||||
NSTimeZone *tz = [NSTimeZone localTimeZone];
|
||||
BOOL ampm = NO;
|
||||
BOOL twelveHrClock = NO;
|
||||
int julianWeeks = -1, weekStartsMonday = 0, dayOfWeek = -1;
|
||||
const char *source = [description cString];
|
||||
int sourceLen = strlen(source);
|
||||
const char *format = [fmt cString];
|
||||
int formatLen = strlen(format);
|
||||
int formatIdx = 0;
|
||||
int sourceIdx = 0;
|
||||
char tmpStr[20];
|
||||
int tmpIdx;
|
||||
|
||||
if (locale == nil)
|
||||
{
|
||||
locale = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
|
||||
}
|
||||
{
|
||||
locale = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
|
||||
}
|
||||
if (fmt == nil)
|
||||
{
|
||||
{
|
||||
format = [[locale objectForKey: NSTimeDateFormatString] cString];
|
||||
formatLen = strlen(format);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// WARNING:
|
||||
|
@ -236,299 +245,357 @@
|
|||
// %Y year as a decimal number with century
|
||||
// %z time zone offset in hours and minutes from GMT (HHMM)
|
||||
// %Z time zone abbreviation
|
||||
while ( formatIdx < formatLen )
|
||||
|
||||
while (formatIdx < formatLen)
|
||||
{
|
||||
if (format[formatIdx] != '%')
|
||||
{
|
||||
if ( format[formatIdx] != '%' )
|
||||
{
|
||||
// If it's not a format specifier, ignore it.
|
||||
sourceIdx++;
|
||||
} else {
|
||||
|
||||
// Skip '%'
|
||||
formatIdx++;
|
||||
|
||||
switch (format[formatIdx])
|
||||
{
|
||||
case '%':
|
||||
// skip literal %
|
||||
sourceIdx++;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
// Are Short names three chars in all locales?????
|
||||
tmpStr[0] = toupper( source[sourceIdx++] );
|
||||
tmpStr[1] = tolower( source[sourceIdx++] );
|
||||
tmpStr[2] = tolower( source[sourceIdx++] );
|
||||
tmpStr[3] = '\0';
|
||||
{
|
||||
NSString *currDay = [NSString stringWithCString: tmpStr];
|
||||
NSArray *dayNames = [locale objectForKey: NSShortWeekDayNameArray];
|
||||
|
||||
for (tmpIdx = 0; tmpIdx < 7; tmpIdx++)
|
||||
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay] == YES)
|
||||
break;
|
||||
dayOfWeek = tmpIdx;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
for ( tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++ )
|
||||
{
|
||||
if ( isalpha( source[tmpIdx] ) )
|
||||
{
|
||||
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmpStr[tmpIdx - sourceIdx] = '\0';
|
||||
sourceIdx += tmpIdx - sourceIdx;
|
||||
{
|
||||
NSString *currDay = [NSString stringWithCString: tmpStr];
|
||||
NSArray *dayNames = [locale objectForKey: NSWeekDayNameArray];
|
||||
|
||||
for (tmpIdx = 0; tmpIdx < 7; tmpIdx++)
|
||||
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay] == YES)
|
||||
break;
|
||||
dayOfWeek = tmpIdx;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
// Are Short names three chars in all locales?????
|
||||
tmpStr[0] = toupper( source[sourceIdx++] );
|
||||
tmpStr[1] = tolower( source[sourceIdx++] );
|
||||
tmpStr[2] = tolower( source[sourceIdx++] );
|
||||
tmpStr[3] = '\0';
|
||||
{
|
||||
NSString *currMonth = [NSString stringWithCString: tmpStr];
|
||||
NSArray *monthNames = [locale objectForKey: NSShortMonthNameArray];
|
||||
|
||||
for (tmpIdx = 0; tmpIdx < 12; tmpIdx++)
|
||||
{
|
||||
if ([[monthNames objectAtIndex: tmpIdx] isEqual: currMonth] == YES)
|
||||
break;
|
||||
}
|
||||
month = tmpIdx+1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
for ( tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++ )
|
||||
{
|
||||
if ( isalpha( source[tmpIdx] ) )
|
||||
{
|
||||
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmpStr[tmpIdx - sourceIdx] = '\0';
|
||||
sourceIdx += tmpIdx - sourceIdx;
|
||||
{
|
||||
NSString *currMonth = [NSString stringWithCString: tmpStr];
|
||||
NSArray *monthNames = [locale objectForKey: NSMonthNameArray];
|
||||
|
||||
for (tmpIdx = 0; tmpIdx < 12; tmpIdx++)
|
||||
if ([[monthNames objectAtIndex: tmpIdx] isEqual: currMonth] == YES)
|
||||
break;
|
||||
month = tmpIdx+1;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// case 'c':
|
||||
// break;
|
||||
|
||||
case 'd': // fall through
|
||||
case 'e':
|
||||
memcpy( tmpStr, &source[sourceIdx], 2 );
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
day = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
// case 'F':
|
||||
// break;
|
||||
|
||||
case 'I': // fall through
|
||||
twelveHrClock = 1;
|
||||
case 'H':
|
||||
memcpy( tmpStr, &source[sourceIdx], 2 );
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
hour = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
memcpy( tmpStr, &source[sourceIdx], 3 );
|
||||
tmpStr[3] = '\0';
|
||||
sourceIdx += 3;
|
||||
day = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
memcpy( tmpStr, &source[sourceIdx], 2 );
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
month = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
memcpy( tmpStr, &source[sourceIdx], 2 );
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
min = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
// Questionable assumption that all am/pm indicators are 2
|
||||
// characters and in upper case....
|
||||
tmpStr[0] = toupper( source[sourceIdx++] );
|
||||
tmpStr[1] = toupper( source[sourceIdx++] );
|
||||
tmpStr[2] = '\0';
|
||||
{
|
||||
NSString *currAMPM = [NSString stringWithCString: tmpStr];
|
||||
NSArray *amPMNames = [locale objectForKey: NSAMPMDesignation];
|
||||
|
||||
/*
|
||||
* The time addition is handled below because this
|
||||
* indicator only modifies the time on a 12hour clock.
|
||||
*/
|
||||
if ([[amPMNames objectAtIndex: 1] isEqual: currAMPM] == YES)
|
||||
ampm = 1;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
memcpy( tmpStr, &source[sourceIdx], 2 );
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
sec = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
tmpStr[0] = source[sourceIdx++];
|
||||
tmpStr[1] = '\0';
|
||||
dayOfWeek = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
case 'W': // Fall through
|
||||
weekStartsMonday = 1;
|
||||
case 'U':
|
||||
memcpy( tmpStr, &source[sourceIdx], 2 );
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
julianWeeks = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
// case 'x':
|
||||
// break;
|
||||
|
||||
// case 'X':
|
||||
// break;
|
||||
|
||||
case 'y':
|
||||
memcpy( tmpStr, &source[sourceIdx], 2 );
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
year = atoi( tmpStr );
|
||||
if ( year >= 70 )
|
||||
{
|
||||
year += 1900;
|
||||
} else {
|
||||
year += 2000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
memcpy( tmpStr, &source[sourceIdx], 4 );
|
||||
tmpStr[4] = '\0';
|
||||
sourceIdx += 4;
|
||||
year = atoi( tmpStr );
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
tmpStr[0] = toupper( source[sourceIdx++] );
|
||||
tmpStr[1] = tolower( source[sourceIdx++] );
|
||||
tmpStr[2] = tolower( source[sourceIdx++] );
|
||||
tmpStr[3] = tolower( source[sourceIdx++] );
|
||||
tmpStr[4] = '\0';
|
||||
{
|
||||
int zone;
|
||||
zone = atoi( tmpStr );
|
||||
if ((tz = [NSTimeZone timeZoneForSecondsFromGMT:
|
||||
(zone / 100 * 60 + (zone % 100) ) * 60] ) == nil )
|
||||
{
|
||||
tz = [NSTimeZone localTimeZone];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
for ( tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++ )
|
||||
{
|
||||
if ( isalpha( source[tmpIdx] ) || source[tmpIdx] == '-' || source[tmpIdx] == '+' )
|
||||
{
|
||||
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmpStr[tmpIdx - sourceIdx] = '\0';
|
||||
sourceIdx += tmpIdx - sourceIdx;
|
||||
{
|
||||
if ( (tz = [NSTimeZone timeZoneWithAbbreviation:
|
||||
[NSString stringWithCString: tmpStr]]) == nil)
|
||||
{
|
||||
tz = [NSTimeZone localTimeZone];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Invalid NSCalendar date, specifier %c not recognized in format %s",
|
||||
format[formatIdx], format];
|
||||
}
|
||||
}
|
||||
formatIdx++;
|
||||
// If it's not a format specifier, ignore it.
|
||||
sourceIdx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip '%'
|
||||
formatIdx++;
|
||||
|
||||
if ( twelveHrClock )
|
||||
{
|
||||
if ( ampm && hour != 12 )
|
||||
{
|
||||
hour += 12;
|
||||
}
|
||||
}
|
||||
switch (format[formatIdx])
|
||||
{
|
||||
case '%':
|
||||
// skip literal %
|
||||
sourceIdx++;
|
||||
break;
|
||||
|
||||
if ( julianWeeks != -1 )
|
||||
{
|
||||
int currDay = [[[[NSCalendarDate alloc] initWithYear: year month: 1 day: 1 hour: 0 minute: 0
|
||||
second: 0 timeZone: [NSTimeZone timeZoneForSecondsFromGMT: 0]] autorelease] dayOfWeek];
|
||||
case 'a':
|
||||
// Are Short names three chars in all locales?????
|
||||
tmpStr[0] = toupper(source[sourceIdx++]);
|
||||
tmpStr[1] = tolower(source[sourceIdx++]);
|
||||
tmpStr[2] = tolower(source[sourceIdx++]);
|
||||
tmpStr[3] = '\0';
|
||||
{
|
||||
NSString *currDay;
|
||||
NSArray *dayNames;
|
||||
|
||||
/*
|
||||
* The julian weeks are either sunday relative or monday relative but all
|
||||
* of the day of week specifiers are sunday relative. This means that if
|
||||
* no day of week specifier was used the week starts on monday.
|
||||
*/
|
||||
if ( dayOfWeek == -1 )
|
||||
{
|
||||
if ( weekStartsMonday )
|
||||
currDay = [NSString stringWithCString: tmpStr];
|
||||
dayNames = [locale objectForKey: NSShortWeekDayNameArray];
|
||||
for (tmpIdx = 0; tmpIdx < 7; tmpIdx++)
|
||||
{
|
||||
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay]
|
||||
== YES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
dayOfWeek = tmpIdx;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
for (tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++)
|
||||
{
|
||||
dayOfWeek = 1;
|
||||
} else {
|
||||
dayOfWeek = 0;
|
||||
if (isalpha(source[tmpIdx]))
|
||||
{
|
||||
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
day = dayOfWeek + (julianWeeks * 7 - (currDay - 1));
|
||||
}
|
||||
tmpStr[tmpIdx - sourceIdx] = '\0';
|
||||
sourceIdx += tmpIdx - sourceIdx;
|
||||
{
|
||||
NSString *currDay;
|
||||
NSArray *dayNames;
|
||||
|
||||
return [[NSCalendarDate alloc] initWithYear: year month: month day: day hour: hour
|
||||
minute: min second: sec
|
||||
timeZone: tz];
|
||||
currDay = [NSString stringWithCString: tmpStr];
|
||||
dayNames = [locale objectForKey: NSWeekDayNameArray];
|
||||
for (tmpIdx = 0; tmpIdx < 7; tmpIdx++)
|
||||
{
|
||||
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay]
|
||||
== YES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
dayOfWeek = tmpIdx;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
// Are Short names three chars in all locales?????
|
||||
tmpStr[0] = toupper(source[sourceIdx++]);
|
||||
tmpStr[1] = tolower(source[sourceIdx++]);
|
||||
tmpStr[2] = tolower(source[sourceIdx++]);
|
||||
tmpStr[3] = '\0';
|
||||
{
|
||||
NSString *currMonth;
|
||||
NSArray *monthNames;
|
||||
|
||||
currMonth = [NSString stringWithCString: tmpStr];
|
||||
monthNames = [locale objectForKey: NSShortMonthNameArray];
|
||||
|
||||
for (tmpIdx = 0; tmpIdx < 12; tmpIdx++)
|
||||
{
|
||||
if ([[monthNames objectAtIndex: tmpIdx]
|
||||
isEqual: currMonth] == YES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
month = tmpIdx+1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
for (tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++)
|
||||
{
|
||||
if (isalpha(source[tmpIdx]))
|
||||
{
|
||||
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmpStr[tmpIdx - sourceIdx] = '\0';
|
||||
sourceIdx += tmpIdx - sourceIdx;
|
||||
{
|
||||
NSString *currMonth;
|
||||
NSArray *monthNames;
|
||||
|
||||
currMonth = [NSString stringWithCString: tmpStr];
|
||||
monthNames = [locale objectForKey: NSMonthNameArray];
|
||||
|
||||
for (tmpIdx = 0; tmpIdx < 12; tmpIdx++)
|
||||
{
|
||||
if ([[monthNames objectAtIndex: tmpIdx]
|
||||
isEqual: currMonth] == YES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
month = tmpIdx+1;
|
||||
}
|
||||
break;
|
||||
|
||||
// case 'c':
|
||||
// break;
|
||||
|
||||
case 'd': // fall through
|
||||
case 'e':
|
||||
memcpy(tmpStr, &source[sourceIdx], 2);
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
day = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
// case 'F':
|
||||
// break;
|
||||
|
||||
case 'I': // fall through
|
||||
twelveHrClock = YES;
|
||||
case 'H':
|
||||
memcpy(tmpStr, &source[sourceIdx], 2);
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
hour = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
memcpy(tmpStr, &source[sourceIdx], 3);
|
||||
tmpStr[3] = '\0';
|
||||
sourceIdx += 3;
|
||||
day = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
memcpy(tmpStr, &source[sourceIdx], 2);
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
month = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
memcpy(tmpStr, &source[sourceIdx], 2);
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
min = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
// Questionable assumption that all am/pm indicators are 2
|
||||
// characters and in upper case....
|
||||
tmpStr[0] = toupper(source[sourceIdx++]);
|
||||
tmpStr[1] = toupper(source[sourceIdx++]);
|
||||
tmpStr[2] = '\0';
|
||||
{
|
||||
NSString *currAMPM;
|
||||
NSArray *amPMNames;
|
||||
|
||||
currAMPM = [NSString stringWithCString: tmpStr];
|
||||
amPMNames = [locale objectForKey: NSAMPMDesignation];
|
||||
|
||||
/*
|
||||
* The time addition is handled below because this
|
||||
* indicator only modifies the time on a 12hour clock.
|
||||
*/
|
||||
if ([[amPMNames objectAtIndex: 1] isEqual: currAMPM] == YES)
|
||||
{
|
||||
ampm = YES;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
memcpy(tmpStr, &source[sourceIdx], 2);
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
sec = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
tmpStr[0] = source[sourceIdx++];
|
||||
tmpStr[1] = '\0';
|
||||
dayOfWeek = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
case 'W': // Fall through
|
||||
weekStartsMonday = 1;
|
||||
case 'U':
|
||||
memcpy(tmpStr, &source[sourceIdx], 2);
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
julianWeeks = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
// case 'x':
|
||||
// break;
|
||||
|
||||
// case 'X':
|
||||
// break;
|
||||
|
||||
case 'y':
|
||||
memcpy(tmpStr, &source[sourceIdx], 2);
|
||||
tmpStr[2] = '\0';
|
||||
sourceIdx += 2;
|
||||
year = atoi(tmpStr);
|
||||
if (year >= 70)
|
||||
{
|
||||
year += 1900;
|
||||
}
|
||||
else
|
||||
{
|
||||
year += 2000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
memcpy(tmpStr, &source[sourceIdx], 4);
|
||||
tmpStr[4] = '\0';
|
||||
sourceIdx += 4;
|
||||
year = atoi(tmpStr);
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
tmpStr[0] = toupper(source[sourceIdx++]);
|
||||
tmpStr[1] = tolower(source[sourceIdx++]);
|
||||
tmpStr[2] = tolower(source[sourceIdx++]);
|
||||
tmpStr[3] = tolower(source[sourceIdx++]);
|
||||
tmpStr[4] = '\0';
|
||||
{
|
||||
int zone = atoi(tmpStr);
|
||||
|
||||
if ((tz = [NSTimeZone timeZoneForSecondsFromGMT:
|
||||
(zone / 100 * 60 + (zone % 100)) * 60]) == nil)
|
||||
{
|
||||
tz = [NSTimeZone localTimeZone];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
for (tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++)
|
||||
{
|
||||
if (isalpha(source[tmpIdx]) || source[tmpIdx] == '-'
|
||||
|| source[tmpIdx] == '+')
|
||||
{
|
||||
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmpStr[tmpIdx - sourceIdx] = '\0';
|
||||
sourceIdx += tmpIdx - sourceIdx;
|
||||
{
|
||||
if ((tz = [NSTimeZone timeZoneWithAbbreviation:
|
||||
[NSString stringWithCString: tmpStr]]) == nil)
|
||||
{
|
||||
tz = [NSTimeZone localTimeZone];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
[NSException raise: NSInvalidArgumentException format:
|
||||
@"Invalid NSCalendar date, specifier %c not recognized in format %s", format[formatIdx], format];
|
||||
}
|
||||
}
|
||||
formatIdx++;
|
||||
}
|
||||
|
||||
if (twelveHrClock == YES)
|
||||
{
|
||||
if (ampm == YES && hour != 12)
|
||||
{
|
||||
hour += 12;
|
||||
}
|
||||
}
|
||||
|
||||
if (julianWeeks != -1)
|
||||
{
|
||||
NSTimeZone *gmtZone;
|
||||
NSCalendarDate *d;
|
||||
int currDay;
|
||||
|
||||
gmtZone = [NSTimeZone timeZoneForSecondsFromGMT: 0];
|
||||
d = [NSCalendarDate dateWithYear: year
|
||||
month: 1
|
||||
day: 1
|
||||
hour: 0
|
||||
minute: 0
|
||||
second: 0
|
||||
timeZone: gmtZone];
|
||||
currDay = [d dayOfWeek];
|
||||
|
||||
/*
|
||||
* The julian weeks are either sunday relative or monday relative but all
|
||||
* of the day of week specifiers are sunday relative. This means that if
|
||||
* no day of week specifier was used the week starts on monday.
|
||||
*/
|
||||
if (dayOfWeek == -1)
|
||||
{
|
||||
if (weekStartsMonday)
|
||||
{
|
||||
dayOfWeek = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dayOfWeek = 0;
|
||||
}
|
||||
}
|
||||
day = dayOfWeek + (julianWeeks * 7 - (currDay - 1));
|
||||
}
|
||||
|
||||
return [[NSCalendarDate alloc] initWithYear: year
|
||||
month: month
|
||||
day: day
|
||||
hour: hour
|
||||
minute: min
|
||||
second: sec
|
||||
timeZone: tz];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1115,18 +1115,6 @@ GSTimeNow()
|
|||
|
||||
// Adding and getting intervals
|
||||
|
||||
- (id) addTimeInterval: (NSTimeInterval)seconds
|
||||
{
|
||||
/* xxx We need to check for overflow? */
|
||||
id newObj = [[self class] dateWithTimeIntervalSinceReferenceDate:
|
||||
_seconds_since_ref + seconds];
|
||||
|
||||
if ([self isKindOfClass: [NSCalendarDate class]])
|
||||
[newObj setTimeZone: [(NSCalendarDate *) self timeZoneDetail]];
|
||||
|
||||
return newObj;
|
||||
}
|
||||
|
||||
- (NSTimeInterval) timeIntervalSince1970
|
||||
{
|
||||
return _seconds_since_ref - UNIX_REFERENCE_INTERVAL;
|
||||
|
|
|
@ -432,17 +432,26 @@ static SEL eqSel = @selector(isEqual:);
|
|||
index = _count;
|
||||
if (index > 0)
|
||||
{
|
||||
BOOL (*imp)(id,SEL,id);
|
||||
BOOL (*imp)(id,SEL,id);
|
||||
#if GS_WITH_GC == 0
|
||||
BOOL retained = NO;
|
||||
#endif
|
||||
|
||||
imp = (BOOL (*)(id,SEL,id))[anObject methodForSelector: eqSel];
|
||||
while (index-- > 0)
|
||||
{
|
||||
if ((*imp)(anObject, eqSel, _contents_array[index]) == YES)
|
||||
{
|
||||
unsigned pos = index;
|
||||
#if GS_WITH_GC == 0
|
||||
id obj = _contents_array[index];
|
||||
|
||||
if (retained == NO)
|
||||
{
|
||||
RETAIN(anObject);
|
||||
retained = YES;
|
||||
}
|
||||
#endif
|
||||
unsigned pos = index;
|
||||
|
||||
while (++pos < _count)
|
||||
{
|
||||
|
@ -450,13 +459,14 @@ static SEL eqSel = @selector(isEqual:);
|
|||
}
|
||||
_count--;
|
||||
RELEASE(obj);
|
||||
/*
|
||||
* Bail out now or run the risk of comparing against a garbage
|
||||
* pointer.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if GS_WITH_GC == 0
|
||||
if (retained == YES)
|
||||
{
|
||||
RELEASE(anObject);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,11 +515,6 @@ static SEL eqSel = @selector(isEqual:);
|
|||
}
|
||||
_count--;
|
||||
RELEASE(obj);
|
||||
/*
|
||||
* Bail out now or run the risk of comparing against a garbage
|
||||
* pointer.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
138
Source/NSLock.m
138
Source/NSLock.m
|
@ -97,41 +97,43 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
|
|||
{
|
||||
// Ask the runtime to acquire a lock on the mutex
|
||||
if (objc_mutex_trylock(_mutex) == -1)
|
||||
{
|
||||
{
|
||||
return NO;
|
||||
} else {
|
||||
/*
|
||||
* The recursive lock check goes here to support openstep's
|
||||
* implementation. In openstep you can lock in one thread trylock in the
|
||||
* same thread and have another thread release the lock.
|
||||
*
|
||||
* This is dangerous and broken IMHO.
|
||||
*/
|
||||
CHECK_RECURSIVE_LOCK(_mutex);
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The recursive lock check goes here to support openstep's
|
||||
* implementation. In openstep you can lock in one thread trylock in the
|
||||
* same thread and have another thread release the lock.
|
||||
*
|
||||
* This is dangerous and broken IMHO.
|
||||
*/
|
||||
CHECK_RECURSIVE_LOCK(_mutex);
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) lockBeforeDate: (NSDate *)limit
|
||||
{
|
||||
int x;
|
||||
|
||||
while ((x = objc_mutex_trylock (_mutex)) == -1 )
|
||||
while ((x = objc_mutex_trylock(_mutex)) == -1)
|
||||
{
|
||||
NSDate *current = [NSDate date];
|
||||
NSComparisonResult compare;
|
||||
|
||||
compare = [current compare: limit];
|
||||
if (compare == NSOrderedSame || compare == NSOrderedDescending)
|
||||
{
|
||||
NSDate *current = [NSDate date];
|
||||
NSComparisonResult compare;
|
||||
|
||||
compare = [current compare: limit];
|
||||
if ( compare == NSOrderedSame || compare == NSOrderedDescending )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* This should probably be more accurate like usleep(250)
|
||||
* but usleep is known to NOT be thread safe under all architectures.
|
||||
*/
|
||||
sleep(1);
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* This should probably be more accurate like usleep(250)
|
||||
* but usleep is known to NOT be thread safe under all architectures.
|
||||
*/
|
||||
sleep(1);
|
||||
}
|
||||
/*
|
||||
* The recursive lock check goes here to support openstep's implementation.
|
||||
* In openstep you can lock in one thread trylock in the same thread and have
|
||||
|
@ -334,22 +336,22 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
|
|||
{
|
||||
CHECK_RECURSIVE_CONDITION_LOCK(_mutex);
|
||||
|
||||
while ( objc_mutex_trylock (_mutex) == -1 )
|
||||
while (objc_mutex_trylock(_mutex) == -1)
|
||||
{
|
||||
NSDate *current = [NSDate date];
|
||||
NSComparisonResult compare;
|
||||
|
||||
compare = [current compare: limit];
|
||||
if (compare == NSOrderedSame || compare == NSOrderedDescending)
|
||||
{
|
||||
NSDate *current = [NSDate date];
|
||||
NSComparisonResult compare;
|
||||
|
||||
compare = [current compare: limit];
|
||||
if ( compare == NSOrderedSame || compare == NSOrderedDescending )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* This should probably be more accurate like usleep(250)
|
||||
* but usleep is known to NOT be thread safe under all architectures.
|
||||
*/
|
||||
sleep(1);
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* This should probably be more accurate like usleep(250)
|
||||
* but usleep is known to NOT be thread safe under all architectures.
|
||||
*/
|
||||
sleep(1);
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
@ -378,22 +380,22 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
|
|||
endtime.tv_nsec = (unsigned int)((atimeinterval - (float)endtime.tv_sec)
|
||||
* 1000000000.0);
|
||||
|
||||
while( _condition_value != condition_to_meet)
|
||||
while (_condition_value != condition_to_meet)
|
||||
{
|
||||
switch(objc_condition_timedwait(_condition, _mutex, &endtime))
|
||||
switch (objc_condition_timedwait(_condition, _mutex, &endtime))
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case EINTR:
|
||||
break;
|
||||
case ETIMEDOUT :
|
||||
[self unlock];
|
||||
return NO;
|
||||
default:
|
||||
[NSException raise:NSConditionLockException
|
||||
format:@"objc_condition_timedwait failed"];
|
||||
[self unlock];
|
||||
return NO;
|
||||
case 0:
|
||||
break;
|
||||
case EINTR:
|
||||
break;
|
||||
case ETIMEDOUT :
|
||||
[self unlock];
|
||||
return NO;
|
||||
default:
|
||||
[NSException raise:NSConditionLockException
|
||||
format:@"objc_condition_timedwait failed"];
|
||||
[self unlock];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
|
@ -488,22 +490,22 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
|
|||
|
||||
- (BOOL) lockBeforeDate: (NSDate *)limit
|
||||
{
|
||||
while ( objc_mutex_trylock (_mutex) == -1 )
|
||||
while (objc_mutex_trylock(_mutex) == -1)
|
||||
{
|
||||
NSDate *current = [NSDate date];
|
||||
NSComparisonResult compare;
|
||||
|
||||
compare = [current compare: limit];
|
||||
if (compare == NSOrderedSame || compare == NSOrderedDescending)
|
||||
{
|
||||
NSDate *current = [NSDate date];
|
||||
NSComparisonResult compare;
|
||||
|
||||
compare = [current compare: limit];
|
||||
if ( compare == NSOrderedSame || compare == NSOrderedDescending )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* This should probably be more accurate like usleep(250)
|
||||
* but usleep is known to NOT be thread safe under all architectures.
|
||||
*/
|
||||
sleep(1);
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* This should probably be more accurate like usleep(250)
|
||||
* but usleep is known to NOT be thread safe under all architectures.
|
||||
*/
|
||||
sleep(1);
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#include <Foundation/NSDistantObject.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <Foundation/NSDebug.h>
|
||||
#include <Foundation/NSThread.h>
|
||||
#include <Foundation/NSNotification.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <base/fast.x>
|
||||
|
@ -103,6 +105,12 @@ void _fastBuildCache()
|
|||
* correct zone to free memory very fast.
|
||||
*/
|
||||
|
||||
/*
|
||||
* retain_counts_gate is needed when running multi-threaded for retain/release
|
||||
* to work reliably.
|
||||
*/
|
||||
static objc_mutex_t retain_counts_gate = NULL;
|
||||
|
||||
#if GS_WITH_GC == 0
|
||||
#define REFCNT_LOCAL 1
|
||||
#define CACHE_ZONE 1
|
||||
|
@ -182,33 +190,62 @@ NSExtraRefCount(id anObject)
|
|||
return ((obj)anObject)[-1].retained;
|
||||
}
|
||||
|
||||
static objc_mutex_t retain_counts_gate = NULL;
|
||||
|
||||
void
|
||||
NSIncrementExtraRefCount(id anObject)
|
||||
{
|
||||
objc_mutex_lock (retain_counts_gate);
|
||||
((obj)anObject)[-1].retained++;
|
||||
objc_mutex_unlock (retain_counts_gate);
|
||||
if (retain_counts_gate != 0)
|
||||
{
|
||||
objc_mutex_lock(retain_counts_gate);
|
||||
((obj)anObject)[-1].retained++;
|
||||
objc_mutex_unlock (retain_counts_gate);
|
||||
}
|
||||
else
|
||||
{
|
||||
((obj)anObject)[-1].retained++;
|
||||
}
|
||||
}
|
||||
|
||||
#define NSIncrementExtraRefCount(X) \
|
||||
objc_mutex_lock (retain_counts_gate); \
|
||||
((obj)(X))[-1].retained++; \
|
||||
objc_mutex_unlock (retain_counts_gate)
|
||||
#define NSIncrementExtraRefCount(X) ({ \
|
||||
if (retain_counts_gate != 0) \
|
||||
{ \
|
||||
objc_mutex_lock(retain_counts_gate); \
|
||||
((obj)(X))[-1].retained++; \
|
||||
objc_mutex_unlock(retain_counts_gate); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
((obj)X)[-1].retained++; \
|
||||
} \
|
||||
})
|
||||
|
||||
BOOL
|
||||
NSDecrementExtraRefCountWasZero(id anObject)
|
||||
{
|
||||
objc_mutex_lock (retain_counts_gate);
|
||||
if (((obj)anObject)[-1].retained-- == 0)
|
||||
if (retain_counts_gate != 0)
|
||||
{
|
||||
objc_mutex_lock(retain_counts_gate);
|
||||
if (((obj)anObject)[-1].retained-- == 0)
|
||||
{
|
||||
objc_mutex_unlock (retain_counts_gate);
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
return YES;
|
||||
} else {
|
||||
objc_mutex_unlock (retain_counts_gate);
|
||||
}
|
||||
else
|
||||
{
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((obj)anObject)[-1].retained-- == 0)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -218,22 +255,31 @@ NSDecrementExtraRefCountWasZero(id anObject)
|
|||
|
||||
/* The maptable of retain counts on objects */
|
||||
static o_map_t *retain_counts = NULL;
|
||||
/* The mutex lock to protect multi-threaded use of `retain_counts' */
|
||||
static objc_mutex_t retain_counts_gate = NULL;
|
||||
|
||||
void
|
||||
NSIncrementExtraRefCount (id anObject)
|
||||
{
|
||||
o_map_node_t *node;
|
||||
extern o_map_node_t *o_map_node_for_key (o_map_t *m, const void *k);
|
||||
extern o_map_node_t *o_map_node_for_key(o_map_t *m, const void *k);
|
||||
|
||||
objc_mutex_lock (retain_counts_gate);
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (node)
|
||||
((int)(node->value))++;
|
||||
if (retain_counts_gate != 0)
|
||||
{
|
||||
objc_mutex_lock(retain_counts_gate);
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (node)
|
||||
((int)(node->value))++;
|
||||
else
|
||||
o_map_at_key_put_value_known_absent (retain_counts, anObject, (void*)1);
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
}
|
||||
else
|
||||
o_map_at_key_put_value_known_absent (retain_counts, anObject, (void*)1);
|
||||
objc_mutex_unlock (retain_counts_gate);
|
||||
{
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (node)
|
||||
((int)(node->value))++;
|
||||
else
|
||||
o_map_at_key_put_value_known_absent (retain_counts, anObject, (void*)1);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
|
@ -243,17 +289,35 @@ NSDecrementExtraRefCountWasZero (id anObject)
|
|||
extern o_map_node_t *o_map_node_for_key (o_map_t *m, const void *k);
|
||||
extern void o_map_remove_node (o_map_node_t *node);
|
||||
|
||||
objc_mutex_lock (retain_counts_gate);
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (!node)
|
||||
if (retain_counts_gate != 0)
|
||||
{
|
||||
objc_mutex_unlock (retain_counts_gate);
|
||||
return YES;
|
||||
objc_mutex_lock(retain_counts_gate);
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (!node)
|
||||
{
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
return YES;
|
||||
}
|
||||
NSAssert((int)(node->value) > 0, NSInternalInconsistencyException);
|
||||
if (!--((int)(node->value)))
|
||||
{
|
||||
o_map_remove_node (node);
|
||||
}
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (!node)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
NSAssert((int)(node->value) > 0, NSInternalInconsistencyException);
|
||||
if (!--((int)(node->value)))
|
||||
{
|
||||
o_map_remove_node (node);
|
||||
}
|
||||
}
|
||||
NSAssert((int)(node->value) > 0, NSInternalInconsistencyException);
|
||||
if (!--((int)(node->value)))
|
||||
o_map_remove_node (node);
|
||||
objc_mutex_unlock (retain_counts_gate);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -262,11 +326,26 @@ NSExtraRefCount (id anObject)
|
|||
{
|
||||
unsigned ret;
|
||||
|
||||
objc_mutex_lock (retain_counts_gate);
|
||||
ret = (unsigned) o_map_value_at_key (retain_counts, anObject);
|
||||
if (ret == (unsigned)o_map_not_a_key_marker(retain_counts) ||
|
||||
ret == (unsigned)o_map_not_a_value_marker(retain_counts)) ret = 0;
|
||||
objc_mutex_unlock (retain_counts_gate);
|
||||
if (retain_counts_gate != 0)
|
||||
{
|
||||
objc_mutex_lock(retain_counts_gate);
|
||||
ret = (unsigned) o_map_value_at_key(retain_counts, anObject);
|
||||
if (ret == (unsigned)o_map_not_a_key_marker(retain_counts)
|
||||
|| ret == (unsigned)o_map_not_a_value_marker(retain_counts))
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (unsigned) o_map_value_at_key(retain_counts, anObject);
|
||||
if (ret == (unsigned)o_map_not_a_key_marker(retain_counts)
|
||||
|| ret == (unsigned)o_map_not_a_value_marker(retain_counts))
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret; /* ExtraRefCount + 1 */
|
||||
}
|
||||
|
||||
|
@ -501,9 +580,18 @@ static IMP autorelease_imp = 0;
|
|||
This does not need mutex protection. */
|
||||
static BOOL double_release_check_enabled = NO;
|
||||
|
||||
|
||||
|
||||
@implementation NSObject
|
||||
|
||||
+ (void) _becomeMultiThreaded: (NSNotification)aNotification
|
||||
{
|
||||
if (retain_counts_gate == 0)
|
||||
{
|
||||
retain_counts_gate = objc_mutex_allocate();
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSObject class])
|
||||
|
@ -529,16 +617,16 @@ static BOOL double_release_check_enabled = NO;
|
|||
retain_counts = o_map_with_callbacks (o_callbacks_for_non_owned_void_p,
|
||||
o_callbacks_for_int);
|
||||
#endif
|
||||
/*
|
||||
* retain_counts_gate is needed on SMP machines for release to work
|
||||
* reliably.
|
||||
*/
|
||||
retain_counts_gate = objc_mutex_allocate ();
|
||||
fastMallocOffset = fastMallocClass->instance_size % ALIGN;
|
||||
#else
|
||||
fastMallocOffset = 0;
|
||||
#endif
|
||||
_fastBuildCache();
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: self
|
||||
selector: @selector(_becomeMultiThreaded:)
|
||||
name: NSWillBecomeMultiThreadedNotification
|
||||
object: nil];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -674,13 +762,13 @@ static BOOL double_release_check_enabled = NO;
|
|||
|
||||
- (NSString*) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"<%s %lx>",
|
||||
return [NSString stringWithFormat: @"<%s: %lx>",
|
||||
object_get_class_name(self), (unsigned long)self];
|
||||
}
|
||||
|
||||
+ (NSString*) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"<%s>", object_get_class_name(self)];
|
||||
return [NSString stringWithCString: object_get_class_name(self)];
|
||||
}
|
||||
|
||||
- (void) descriptionTo: (id<GNUDescriptionDestination>)output
|
||||
|
@ -781,7 +869,7 @@ static BOOL double_release_check_enabled = NO;
|
|||
|
||||
/* NSObject protocol */
|
||||
|
||||
- autorelease
|
||||
- (id) autorelease
|
||||
{
|
||||
#if GS_WITH_GC == 0
|
||||
if (double_release_check_enabled)
|
||||
|
|
|
@ -972,20 +972,18 @@ static NSMapTable *absolutes = 0;
|
|||
|
||||
+ (NSString*) getTimeZoneFile: (NSString *)name
|
||||
{
|
||||
/*
|
||||
* OpenStep does NOT put all the GMT+-* timezones in the Etc directory so all
|
||||
* the OpenStep software will fail to work without this extra hack.
|
||||
*/
|
||||
NSString *fileName = [NSString stringWithFormat: @"%@%@",
|
||||
ZONES_DIR, name];
|
||||
NSString *fileName = [NSString stringWithFormat: @"%@%@", ZONES_DIR, name];
|
||||
NSString *path = [NSBundle pathForGNUstepResource: fileName
|
||||
ofType: @""
|
||||
inDirectory: TIME_ZONE_DIR];
|
||||
ofType: @""
|
||||
inDirectory: TIME_ZONE_DIR];
|
||||
|
||||
if ( !path )
|
||||
{
|
||||
return [self getTimeZoneFile: [NSString stringWithFormat: @"Etc/%@", name]];
|
||||
}
|
||||
/*
|
||||
* Hack for OPENSTEP storing zones in Etc?
|
||||
*/
|
||||
if (path == nil)
|
||||
{
|
||||
path=[self getTimeZoneFile: [NSString stringWithFormat: @"Etc/%@", name]];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue