mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
NSCalendarDate.m - dateByAddingYears lost timezone info.
- initWithString didn't deal with adjacent format specifiers. NSDate.m - addTimeInterval messed up timezone if used with CalendarDate. NSArray.m - NSMutableArray's comparered against a garbage pointer NSGArray.m on removal. This causes real problems on SMP machines. NSTimeZone.m - The GMT+-xx files on OpenStep are in the root directory and they are in Etc/* in gnustep so check both. NSObject.m - The release code was slightly broken for SMP machine use. NSLock.m - Trylock was broken and lockBeforeDate unimplemented. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@5436 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
c3fb857b06
commit
b35bbfad7e
7 changed files with 479 additions and 291 deletions
|
@ -900,6 +900,11 @@ static NSString *indentStrings[] = {
|
||||||
if (rem == 0)
|
if (rem == 0)
|
||||||
rem = [self methodForSelector: remSel];
|
rem = [self methodForSelector: remSel];
|
||||||
(*rem)(self, remSel, i);
|
(*rem)(self, remSel, i);
|
||||||
|
/*
|
||||||
|
* Bail out now or run the risk of comparing against a garbage
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -939,6 +944,11 @@ static NSString *indentStrings[] = {
|
||||||
if (rem == 0)
|
if (rem == 0)
|
||||||
rem = [self methodForSelector: remSel];
|
rem = [self methodForSelector: remSel];
|
||||||
(*rem)(self, remSel, i);
|
(*rem)(self, remSel, i);
|
||||||
|
/*
|
||||||
|
* Bail out now or run the risk of comparing against a garbage
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -976,6 +986,11 @@ static NSString *indentStrings[] = {
|
||||||
if (rem == 0)
|
if (rem == 0)
|
||||||
rem = [self methodForSelector: remSel];
|
rem = [self methodForSelector: remSel];
|
||||||
(*rem)(self, remSel, i);
|
(*rem)(self, remSel, i);
|
||||||
|
/*
|
||||||
|
* Bail out now or run the risk of comparing against a garbage
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1007,6 +1022,11 @@ static NSString *indentStrings[] = {
|
||||||
if (rem == 0)
|
if (rem == 0)
|
||||||
rem = [self methodForSelector: remSel];
|
rem = [self methodForSelector: remSel];
|
||||||
(*rem)(self, remSel, i);
|
(*rem)(self, remSel, i);
|
||||||
|
/*
|
||||||
|
* Bail out now or run the risk of comparing against a garbage
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,48 +169,57 @@
|
||||||
locale: nil];
|
locale: nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This function could possibly be written better
|
|
||||||
* but it works ok; currently ignores locale
|
|
||||||
* information and some specifiers.
|
|
||||||
*/
|
|
||||||
- (id) initWithString: (NSString *)description
|
|
||||||
calendarFormat: (NSString *)format
|
|
||||||
locale: (NSDictionary *)locale
|
|
||||||
{
|
|
||||||
const char *d = [description cString];
|
|
||||||
const char *f = [format cString];
|
|
||||||
char *newf;
|
|
||||||
int lf = strlen(f);
|
|
||||||
BOOL mtag = NO, dtag = NO, ycent = NO;
|
|
||||||
BOOL fullm = NO;
|
|
||||||
char ms[80] = "", ds[80] = "", timez[80] = "", ampm[80] = "";
|
|
||||||
int tznum = 0;
|
|
||||||
int yd = 0, md = 0, dd = 0, hd = 0, mnd = 0, sd = 0;
|
|
||||||
void *pntr[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
||||||
int order;
|
|
||||||
int yord = 0, mord = 0, dord = 0, hord = 0, mnord = 0, sord = 0, tzord = 0;
|
|
||||||
int ampmord = 0;
|
|
||||||
int i;
|
|
||||||
NSTimeZone *tz;
|
|
||||||
BOOL zoneByAbbreviation = YES;
|
|
||||||
|
|
||||||
// If either the string or format is nil then raise exception
|
- (id) initWithString: (NSString *)description
|
||||||
if (!description)
|
calendarFormat: (NSString *)fmt
|
||||||
[NSException raise: NSInvalidArgumentException
|
locale: (NSDictionary *)locale
|
||||||
format: @"NSCalendar date description is nil"];
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
if (locale == nil)
|
if (locale == nil)
|
||||||
locale = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
|
{
|
||||||
if (format == nil)
|
locale = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
|
||||||
format = [locale objectForKey: NSTimeDateFormatString];
|
}
|
||||||
|
if (fmt == nil)
|
||||||
|
{
|
||||||
|
format = [[locale objectForKey: NSTimeDateFormatString] cString];
|
||||||
|
formatLen = strlen(format);
|
||||||
|
}
|
||||||
|
|
||||||
// The strftime specifiers
|
//
|
||||||
|
// WARNING:
|
||||||
|
// -%c, %F, %x, %X do NOT work. (NSTimeDateFormatString isn't defined and
|
||||||
|
// the underlying call has granularity to the second.
|
||||||
|
// -Most locale stuff is dubious at best.
|
||||||
|
// -Long day and month names depend on a non-alpha character after the last
|
||||||
|
// digit to work.
|
||||||
|
//
|
||||||
|
// The strftime specifiers as used by OpenStep + %U.
|
||||||
|
//
|
||||||
|
// %% literal % character
|
||||||
// %a abbreviated weekday name according to locale
|
// %a abbreviated weekday name according to locale
|
||||||
// %A full weekday name according to locale
|
// %A full weekday name according to locale
|
||||||
// %b abbreviated month name according to locale
|
// %b abbreviated month name according to locale
|
||||||
// %B full month name according to locale
|
// %B full month name according to locale
|
||||||
|
// %c same as '%X %x'
|
||||||
// %d day of month as decimal number
|
// %d day of month as decimal number
|
||||||
|
// %e same as %d without leading zero (you get a leading space instead)
|
||||||
|
// %F milliseconds as a decimal number
|
||||||
// %H hour as a decimal number using 24-hour clock
|
// %H hour as a decimal number using 24-hour clock
|
||||||
// %I hour as a decimal number using 12-hour clock
|
// %I hour as a decimal number using 12-hour clock
|
||||||
// %j day of year as a decimal number
|
// %j day of year as a decimal number
|
||||||
|
@ -221,253 +230,308 @@
|
||||||
// %U week of the current year as decimal number (Sunday first day)
|
// %U week of the current year as decimal number (Sunday first day)
|
||||||
// %W week of the current year as decimal number (Monday first day)
|
// %W week of the current year as decimal number (Monday first day)
|
||||||
// %w day of the week as decimal number (Sunday = 0)
|
// %w day of the week as decimal number (Sunday = 0)
|
||||||
// %y year as a decimal number without century
|
// %x date with date representation for locale
|
||||||
|
// %X time with time representation for locale
|
||||||
|
// %y year as a decimal number without century
|
||||||
// %Y year as a decimal number with century
|
// %Y year as a decimal number with century
|
||||||
// %Z time zone
|
// %z time zone offset in hours and minutes from GMT (HHMM)
|
||||||
// %% literal % character
|
// %Z time zone abbreviation
|
||||||
|
while ( formatIdx < formatLen )
|
||||||
// Find the order of date elements
|
|
||||||
// and translate format string into scanf ready string
|
|
||||||
order = 1;
|
|
||||||
newf = NSZoneMalloc(NSDefaultMallocZone(), lf+1);
|
|
||||||
for (i = 0;i < lf; ++i)
|
|
||||||
{
|
|
||||||
newf[i] = f[i];
|
|
||||||
|
|
||||||
// Only care about a format specifier
|
|
||||||
if (f[i] == '%')
|
|
||||||
{
|
{
|
||||||
// check the character that comes after
|
if ( format[formatIdx] != '%' )
|
||||||
switch (f[i+1])
|
|
||||||
{
|
|
||||||
// skip literal %
|
|
||||||
case '%':
|
|
||||||
++i;
|
|
||||||
newf[i] = f[i];
|
|
||||||
break;
|
|
||||||
|
|
||||||
// is it the year
|
|
||||||
case 'Y':
|
|
||||||
ycent = YES;
|
|
||||||
case 'y':
|
|
||||||
yord = order;
|
|
||||||
++order;
|
|
||||||
++i;
|
|
||||||
newf[i] = 'd';
|
|
||||||
pntr[yord] = (void *)&yd;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// is it the month
|
|
||||||
case 'B':
|
|
||||||
fullm = YES; // Full month name
|
|
||||||
case 'b':
|
|
||||||
mtag = YES; // Month is character string
|
|
||||||
case 'm':
|
|
||||||
mord = order;
|
|
||||||
++order;
|
|
||||||
++i;
|
|
||||||
if (mtag)
|
|
||||||
{
|
{
|
||||||
newf[i] = 's';
|
// If it's not a format specifier, ignore it.
|
||||||
pntr[mord] = (void *)ms;
|
sourceIdx++;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
newf[i] = 'd';
|
|
||||||
pntr[mord] = (void *)&md;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// is it the day
|
// Skip '%'
|
||||||
case 'a':
|
formatIdx++;
|
||||||
case 'A':
|
|
||||||
dtag = YES; // Day is character string
|
|
||||||
case 'd':
|
|
||||||
case 'j':
|
|
||||||
case 'w':
|
|
||||||
dord = order;
|
|
||||||
++order;
|
|
||||||
++i;
|
|
||||||
if (dtag)
|
|
||||||
{
|
|
||||||
newf[i] = 's';
|
|
||||||
pntr[dord] = (void *)ds;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newf[i] = 'd';
|
|
||||||
pntr[dord] = (void *)ⅆ
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// is it the hour
|
switch (format[formatIdx])
|
||||||
case 'H':
|
{
|
||||||
case 'I':
|
case '%':
|
||||||
hord = order;
|
// skip literal %
|
||||||
++order;
|
sourceIdx++;
|
||||||
++i;
|
break;
|
||||||
newf[i] = 'd';
|
|
||||||
pntr[hord] = (void *)&hd;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// is it the minute
|
case 'a':
|
||||||
case 'M':
|
// Are Short names three chars in all locales?????
|
||||||
mnord = order;
|
tmpStr[0] = toupper( source[sourceIdx++] );
|
||||||
++order;
|
tmpStr[1] = tolower( source[sourceIdx++] );
|
||||||
++i;
|
tmpStr[2] = tolower( source[sourceIdx++] );
|
||||||
newf[i] = 'd';
|
tmpStr[3] = '\0';
|
||||||
pntr[mnord] = (void *)&mnd;
|
{
|
||||||
break;
|
NSString *currDay = [NSString stringWithCString: tmpStr];
|
||||||
|
NSArray *dayNames = [locale objectForKey: NSShortWeekDayNameArray];
|
||||||
|
|
||||||
// is it the second
|
for (tmpIdx = 0; tmpIdx < 7; tmpIdx++)
|
||||||
case 'S':
|
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay] == YES)
|
||||||
sord = order;
|
break;
|
||||||
++order;
|
dayOfWeek = tmpIdx;
|
||||||
++i;
|
}
|
||||||
newf[i] = 'd';
|
break;
|
||||||
pntr[sord] = (void *)&sd;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// the time zone abbreviation
|
case 'A':
|
||||||
case 'Z':
|
for ( tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++ )
|
||||||
tzord = order;
|
{
|
||||||
++order;
|
if ( isalpha( source[tmpIdx] ) )
|
||||||
++i;
|
{
|
||||||
newf[i] = 's';
|
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
|
||||||
pntr[tzord] = (void *)timez;
|
} else {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmpStr[tmpIdx - sourceIdx] = '\0';
|
||||||
|
sourceIdx += tmpIdx - sourceIdx;
|
||||||
|
{
|
||||||
|
NSString *currDay = [NSString stringWithCString: tmpStr];
|
||||||
|
NSArray *dayNames = [locale objectForKey: NSWeekDayNameArray];
|
||||||
|
|
||||||
// the time zone in numeric format
|
for (tmpIdx = 0; tmpIdx < 7; tmpIdx++)
|
||||||
case 'z':
|
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay] == YES)
|
||||||
tzord = order;
|
break;
|
||||||
++order;
|
dayOfWeek = tmpIdx;
|
||||||
++i;
|
}
|
||||||
newf[i] = 'd';
|
break;
|
||||||
pntr[tzord] = (void *)&tznum;
|
|
||||||
zoneByAbbreviation = NO;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// AM PM indicator
|
case 'b':
|
||||||
case 'p':
|
// Are Short names three chars in all locales?????
|
||||||
ampmord = order;
|
tmpStr[0] = toupper( source[sourceIdx++] );
|
||||||
++order;
|
tmpStr[1] = tolower( source[sourceIdx++] );
|
||||||
++i;
|
tmpStr[2] = tolower( source[sourceIdx++] );
|
||||||
newf[i] = 's';
|
tmpStr[3] = '\0';
|
||||||
pntr[ampmord] = (void *)ampm;
|
{
|
||||||
break;
|
NSString *currMonth = [NSString stringWithCString: tmpStr];
|
||||||
|
NSArray *monthNames = [locale objectForKey: NSShortMonthNameArray];
|
||||||
|
|
||||||
// Anything else is an invalid format
|
for (tmpIdx = 0; tmpIdx < 12; tmpIdx++)
|
||||||
default:
|
{
|
||||||
free(newf);
|
if ([[monthNames objectAtIndex: tmpIdx] isEqual: currMonth] == YES)
|
||||||
[NSException raise: NSInvalidArgumentException
|
break;
|
||||||
format: @"Invalid NSCalendar date, specifier %c not recognized in format %s", f[i+1], f];
|
}
|
||||||
}
|
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++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
newf[lf] = '\0';
|
|
||||||
|
|
||||||
// Have sscanf parse and retrieve the values for us
|
if ( twelveHrClock )
|
||||||
if (order != 1)
|
{
|
||||||
sscanf(d, newf, pntr[1], pntr[2], pntr[3], pntr[4], pntr[5], pntr[6],
|
if ( ampm && hour != 12 )
|
||||||
pntr[7], pntr[8], pntr[9]);
|
{
|
||||||
else
|
hour += 12;
|
||||||
// nothing in the string?
|
}
|
||||||
;
|
}
|
||||||
|
|
||||||
// Put century on year if need be
|
if ( julianWeeks != -1 )
|
||||||
// +++ How do we be year 2000 compliant?
|
{
|
||||||
if (!ycent)
|
int currDay = [[[[NSCalendarDate alloc] initWithYear: year month: 1 day: 1 hour: 0 minute: 0
|
||||||
yd += 1900;
|
second: 0 timeZone: [NSTimeZone timeZoneForSecondsFromGMT: 0]] autorelease] dayOfWeek];
|
||||||
|
|
||||||
// Possibly convert month from string to decimal number
|
/*
|
||||||
if (mtag)
|
* 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
|
||||||
int i;
|
* no day of week specifier was used the week starts on monday.
|
||||||
NSString *m = [NSString stringWithCString: ms];
|
*/
|
||||||
|
if ( dayOfWeek == -1 )
|
||||||
|
{
|
||||||
|
if ( weekStartsMonday )
|
||||||
|
{
|
||||||
|
dayOfWeek = 1;
|
||||||
|
} else {
|
||||||
|
dayOfWeek = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
day = dayOfWeek + (julianWeeks * 7 - (currDay - 1));
|
||||||
|
}
|
||||||
|
|
||||||
if (fullm)
|
return [[NSCalendarDate alloc] initWithYear: year month: month day: day hour: hour
|
||||||
{
|
minute: min second: sec
|
||||||
NSArray *names = [locale objectForKey: NSMonthNameArray];
|
|
||||||
|
|
||||||
for (i = 0;i < 12; ++i)
|
|
||||||
if ([[names objectAtIndex: i] isEqual: m] == YES)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSArray *names = [locale objectForKey: NSShortMonthNameArray];
|
|
||||||
|
|
||||||
for (i = 0;i < 12; ++i)
|
|
||||||
if ([[names objectAtIndex: i] isEqual: m] == YES)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
md = i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Possibly convert day from string to decimal number
|
|
||||||
// +++ how do we take locale into account?
|
|
||||||
if (dtag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// +++ We need to take 'am' and 'pm' into account
|
|
||||||
if (ampmord)
|
|
||||||
{
|
|
||||||
// If its PM then we shift
|
|
||||||
if ((ampm[0] == 'p') || (ampm[0] == 'P'))
|
|
||||||
{
|
|
||||||
// 12pm is 12pm not 24pm
|
|
||||||
if (hd != 12)
|
|
||||||
hd += 12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// +++ then there is the time zone
|
|
||||||
if (tzord)
|
|
||||||
{
|
|
||||||
if (zoneByAbbreviation)
|
|
||||||
{
|
|
||||||
tz = [NSTimeZone timeZoneWithAbbreviation:
|
|
||||||
[NSString stringWithCString: timez]];
|
|
||||||
if (!tz)
|
|
||||||
{
|
|
||||||
tz = [NSTimeZone localTimeZone];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int tzm, tzh, sign;
|
|
||||||
|
|
||||||
if (tznum < 0)
|
|
||||||
{
|
|
||||||
sign = -1;
|
|
||||||
tznum = -tznum;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sign = 1;
|
|
||||||
}
|
|
||||||
tzm = tznum % 100;
|
|
||||||
tzh = tznum / 100;
|
|
||||||
tz = [NSTimeZone timeZoneForSecondsFromGMT: (tzh*60 + tzm)*60*sign];
|
|
||||||
if (!tz)
|
|
||||||
{
|
|
||||||
tz = [NSTimeZone localTimeZone];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tz = [NSTimeZone localTimeZone];
|
|
||||||
}
|
|
||||||
|
|
||||||
NSZoneFree(NSDefaultMallocZone(), newf);
|
|
||||||
|
|
||||||
return [self initWithYear: yd month: md day: dd hour: hd
|
|
||||||
minute: mnd second: sd
|
|
||||||
timeZone: tz];
|
timeZone: tz];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (id) initWithYear: (int)year
|
- (id) initWithYear: (int)year
|
||||||
month: (unsigned int)month
|
month: (unsigned int)month
|
||||||
day: (unsigned int)day
|
day: (unsigned int)day
|
||||||
|
@ -1252,7 +1316,7 @@
|
||||||
hour: hour
|
hour: hour
|
||||||
minute: minute
|
minute: minute
|
||||||
second: second
|
second: second
|
||||||
timeZone: nil];
|
timeZone: [self timeZoneDetail]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) years: (int*)years
|
- (void) years: (int*)years
|
||||||
|
|
|
@ -1118,8 +1118,13 @@ GSTimeNow()
|
||||||
- (id) addTimeInterval: (NSTimeInterval)seconds
|
- (id) addTimeInterval: (NSTimeInterval)seconds
|
||||||
{
|
{
|
||||||
/* xxx We need to check for overflow? */
|
/* xxx We need to check for overflow? */
|
||||||
return [concreteClass dateWithTimeIntervalSinceReferenceDate:
|
id newObj = [[self class] dateWithTimeIntervalSinceReferenceDate:
|
||||||
_seconds_since_ref + seconds];
|
_seconds_since_ref + seconds];
|
||||||
|
|
||||||
|
if ([self isKindOfClass: [NSCalendarDate class]])
|
||||||
|
[newObj setTimeZone: [(NSCalendarDate *) self timeZoneDetail]];
|
||||||
|
|
||||||
|
return newObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSTimeInterval) timeIntervalSince1970
|
- (NSTimeInterval) timeIntervalSince1970
|
||||||
|
|
|
@ -450,6 +450,11 @@ static SEL eqSel = @selector(isEqual:);
|
||||||
}
|
}
|
||||||
_count--;
|
_count--;
|
||||||
RELEASE(obj);
|
RELEASE(obj);
|
||||||
|
/*
|
||||||
|
* Bail out now or run the risk of comparing against a garbage
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,6 +505,11 @@ static SEL eqSel = @selector(isEqual:);
|
||||||
}
|
}
|
||||||
_count--;
|
_count--;
|
||||||
RELEASE(obj);
|
RELEASE(obj);
|
||||||
|
/*
|
||||||
|
* Bail out now or run the risk of comparing against a garbage
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
100
Source/NSLock.m
100
Source/NSLock.m
|
@ -1,5 +1,5 @@
|
||||||
/* Mutual exclusion locking classes
|
/* Mutual exclusion locking classes
|
||||||
Copyright (C) 1996 Free Software Foundation< Inc.
|
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Author: Scott Christley <scottc@net-community.com>
|
Author: Scott Christley <scottc@net-community.com>
|
||||||
Created: 1996
|
Created: 1996
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2 of the License< or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@ -17,12 +17,13 @@
|
||||||
Library General Public License for more details.
|
Library General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
You should have received a copy of the GNU Library General Public
|
||||||
License along with this library; if not< write to the Free
|
License along with this library; if not, write to the Free
|
||||||
Software Foundation< Inc.< 59 Temple Place< Suite 330< Boston< MA 02111 USA.
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <base/preface.h>
|
#include <base/preface.h>
|
||||||
#include <Foundation/NSLock.h>
|
#include <Foundation/NSLock.h>
|
||||||
#include <Foundation/NSException.h>
|
#include <Foundation/NSException.h>
|
||||||
|
@ -94,19 +95,52 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
|
||||||
// Does not block
|
// Does not block
|
||||||
- (BOOL) tryLock
|
- (BOOL) tryLock
|
||||||
{
|
{
|
||||||
CHECK_RECURSIVE_LOCK(_mutex);
|
|
||||||
|
|
||||||
// Ask the runtime to acquire a lock on the mutex
|
// Ask the runtime to acquire a lock on the mutex
|
||||||
if (objc_mutex_trylock(_mutex) == -1)
|
if (objc_mutex_trylock(_mutex) == -1)
|
||||||
return NO;
|
{
|
||||||
else
|
return NO;
|
||||||
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
|
- (BOOL) lockBeforeDate: (NSDate *)limit
|
||||||
{
|
{
|
||||||
[self notImplemented: _cmd];
|
int x;
|
||||||
return NO;
|
|
||||||
|
while ((x = objc_mutex_trylock (_mutex)) == -1 )
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSLocking protocol
|
// NSLocking protocol
|
||||||
|
@ -236,7 +270,7 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the depth is only 1 then we just acquired
|
// If the depth is only 1 then we just acquired
|
||||||
// the lock above< bogus unlock so abort
|
// the lock above, bogus unlock so abort
|
||||||
if (depth == 1)
|
if (depth == 1)
|
||||||
{
|
{
|
||||||
[NSException raise:NSConditionLockException
|
[NSException raise:NSConditionLockException
|
||||||
|
@ -297,9 +331,26 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
|
||||||
|
|
||||||
// Acquiring the lock with a date condition
|
// Acquiring the lock with a date condition
|
||||||
- (BOOL) lockBeforeDate: (NSDate*)limit
|
- (BOOL) lockBeforeDate: (NSDate*)limit
|
||||||
{
|
{
|
||||||
[self notImplemented: _cmd];
|
CHECK_RECURSIVE_CONDITION_LOCK(_mutex);
|
||||||
return NO;
|
|
||||||
|
while ( objc_mutex_trylock (_mutex) == -1 )
|
||||||
|
{
|
||||||
|
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 YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,8 +488,23 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
|
||||||
|
|
||||||
- (BOOL) lockBeforeDate: (NSDate *)limit
|
- (BOOL) lockBeforeDate: (NSDate *)limit
|
||||||
{
|
{
|
||||||
[self notImplemented: _cmd];
|
while ( objc_mutex_trylock (_mutex) == -1 )
|
||||||
return NO;
|
{
|
||||||
|
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 YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSLocking protocol
|
// NSLocking protocol
|
||||||
|
|
|
@ -175,32 +175,42 @@ NSDecrementExtraRefCountWasZero(id anObject)
|
||||||
* depending on whether we are using local or global counting.
|
* depending on whether we are using local or global counting.
|
||||||
*/
|
*/
|
||||||
#if defined(REFCNT_LOCAL)
|
#if defined(REFCNT_LOCAL)
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
NSExtraRefCount(id anObject)
|
NSExtraRefCount(id anObject)
|
||||||
{
|
{
|
||||||
return ((obj)anObject)[-1].retained;
|
return ((obj)anObject)[-1].retained;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static objc_mutex_t retain_counts_gate = NULL;
|
||||||
|
|
||||||
void
|
void
|
||||||
NSIncrementExtraRefCount(id anObject)
|
NSIncrementExtraRefCount(id anObject)
|
||||||
{
|
{
|
||||||
|
objc_mutex_lock (retain_counts_gate);
|
||||||
((obj)anObject)[-1].retained++;
|
((obj)anObject)[-1].retained++;
|
||||||
|
objc_mutex_unlock (retain_counts_gate);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NSIncrementExtraRefCount(X) \
|
#define NSIncrementExtraRefCount(X) \
|
||||||
((obj)(X))[-1].retained++
|
objc_mutex_lock (retain_counts_gate); \
|
||||||
|
((obj)(X))[-1].retained++; \
|
||||||
|
objc_mutex_unlock (retain_counts_gate)
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
NSDecrementExtraRefCountWasZero(id anObject)
|
NSDecrementExtraRefCountWasZero(id anObject)
|
||||||
{
|
{
|
||||||
|
objc_mutex_lock (retain_counts_gate);
|
||||||
if (((obj)anObject)[-1].retained-- == 0)
|
if (((obj)anObject)[-1].retained-- == 0)
|
||||||
return YES;
|
{
|
||||||
else
|
objc_mutex_unlock (retain_counts_gate);
|
||||||
return NO;
|
return YES;
|
||||||
|
} else {
|
||||||
|
objc_mutex_unlock (retain_counts_gate);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NSDecrementExtraRefCountWasZero(X) \
|
|
||||||
(((obj)(X))[-1].retained-- == 0 ? YES : NO)
|
|
||||||
|
|
||||||
#define NSExtraRefCount(X) (((obj)(X))[-1].retained)
|
#define NSExtraRefCount(X) (((obj)(X))[-1].retained)
|
||||||
|
|
||||||
|
@ -518,8 +528,12 @@ static BOOL double_release_check_enabled = NO;
|
||||||
#if !defined(REFCNT_LOCAL)
|
#if !defined(REFCNT_LOCAL)
|
||||||
retain_counts = o_map_with_callbacks (o_callbacks_for_non_owned_void_p,
|
retain_counts = o_map_with_callbacks (o_callbacks_for_non_owned_void_p,
|
||||||
o_callbacks_for_int);
|
o_callbacks_for_int);
|
||||||
retain_counts_gate = objc_mutex_allocate ();
|
|
||||||
#endif
|
#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;
|
fastMallocOffset = fastMallocClass->instance_size % ALIGN;
|
||||||
#else
|
#else
|
||||||
fastMallocOffset = 0;
|
fastMallocOffset = 0;
|
||||||
|
|
|
@ -972,12 +972,21 @@ static NSMapTable *absolutes = 0;
|
||||||
|
|
||||||
+ (NSString*) getTimeZoneFile: (NSString *)name
|
+ (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: @"%@%@",
|
NSString *fileName = [NSString stringWithFormat: @"%@%@",
|
||||||
ZONES_DIR, name];
|
ZONES_DIR, name];
|
||||||
|
NSString *path = [NSBundle pathForGNUstepResource: fileName
|
||||||
return [NSBundle pathForGNUstepResource: fileName
|
|
||||||
ofType: @""
|
ofType: @""
|
||||||
inDirectory: TIME_ZONE_DIR];
|
inDirectory: TIME_ZONE_DIR];
|
||||||
|
|
||||||
|
if ( !path )
|
||||||
|
{
|
||||||
|
return [self getTimeZoneFile: [NSString stringWithFormat: @"Etc/%@", name]];
|
||||||
|
}
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue