mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 08:41:03 +00:00
Optimise away method call overheads for common timezone operations.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14610 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
e1c37a2dcf
commit
7efb3e5c9d
1 changed files with 117 additions and 27 deletions
|
@ -58,8 +58,81 @@
|
||||||
|
|
||||||
#define GREGORIAN_REFERENCE 730486
|
#define GREGORIAN_REFERENCE 730486
|
||||||
|
|
||||||
|
@class GSTimeZone;
|
||||||
|
@class NSConcreteAbsoluteTimeZone;
|
||||||
|
|
||||||
static NSTimeZone *localTZ = nil;
|
static NSTimeZone *localTZ = nil;
|
||||||
|
|
||||||
|
static Class absClass;
|
||||||
|
static Class dstClass;
|
||||||
|
|
||||||
|
static SEL offSEL;
|
||||||
|
static int (*offIMP)(id, SEL, id);
|
||||||
|
static int (*absOffIMP)(id, SEL, id);
|
||||||
|
static int (*dstOffIMP)(id, SEL, id);
|
||||||
|
|
||||||
|
static SEL abrSEL;
|
||||||
|
static NSString* (*abrIMP)(id, SEL, id);
|
||||||
|
static NSString* (*absAbrIMP)(id, SEL, id);
|
||||||
|
static NSString* (*dstAbrIMP)(id, SEL, id);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the offset from GMT for a date in a timezone ...
|
||||||
|
* Optimize for the local timezone, and less so for the other
|
||||||
|
* base library time zone classes.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
offset(NSTimeZone *tz, NSDate *d)
|
||||||
|
{
|
||||||
|
if (tz == localTZ)
|
||||||
|
{
|
||||||
|
return (*offIMP)(tz, offSEL, d);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Class c = GSObjCClass(tz);
|
||||||
|
|
||||||
|
if (c == dstClass)
|
||||||
|
{
|
||||||
|
return (*dstOffIMP)(tz, offSEL, d);
|
||||||
|
}
|
||||||
|
if (c == absClass)
|
||||||
|
{
|
||||||
|
return (*absOffIMP)(tz, offSEL, d);
|
||||||
|
}
|
||||||
|
return [tz secondsFromGMTForDate: d];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the offset from GMT for a date in a timezone ...
|
||||||
|
* Optimize for the local timezone, and less so for the other
|
||||||
|
* base library time zone classes.
|
||||||
|
*/
|
||||||
|
static inline NSString*
|
||||||
|
abbrev(NSTimeZone *tz, NSDate *d)
|
||||||
|
{
|
||||||
|
if (tz == localTZ)
|
||||||
|
{
|
||||||
|
return (*abrIMP)(tz, abrSEL, d);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Class c = GSObjCClass(tz);
|
||||||
|
|
||||||
|
if (c == dstClass)
|
||||||
|
{
|
||||||
|
return (*dstAbrIMP)(tz, abrSEL, d);
|
||||||
|
}
|
||||||
|
if (c == absClass)
|
||||||
|
{
|
||||||
|
return (*absAbrIMP)(tz, abrSEL, d);
|
||||||
|
}
|
||||||
|
return [tz abbreviationForDate: d];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
lastDayOfGregorianMonth(int month, int year)
|
lastDayOfGregorianMonth(int month, int year)
|
||||||
{
|
{
|
||||||
|
@ -199,6 +272,26 @@ GSBreakTime(NSTimeInterval when, int *year, int *month, int *day,
|
||||||
{
|
{
|
||||||
[self setVersion: 1];
|
[self setVersion: 1];
|
||||||
localTZ = RETAIN([NSTimeZone localTimeZone]);
|
localTZ = RETAIN([NSTimeZone localTimeZone]);
|
||||||
|
|
||||||
|
dstClass = [GSTimeZone class];
|
||||||
|
absClass = [NSConcreteAbsoluteTimeZone class];
|
||||||
|
|
||||||
|
offSEL = @selector(secondsFromGMTForDate:);
|
||||||
|
offIMP = (int (*)(id,SEL,id))
|
||||||
|
[localTZ methodForSelector: offSEL];
|
||||||
|
dstOffIMP = (int (*)(id,SEL,id))
|
||||||
|
[dstClass instanceMethodForSelector: offSEL];
|
||||||
|
absOffIMP = (int (*)(id,SEL,id))
|
||||||
|
[absClass instanceMethodForSelector: offSEL];
|
||||||
|
|
||||||
|
abrSEL = @selector(abbreviationForDate:);
|
||||||
|
abrIMP = (NSString* (*)(id,SEL,id))
|
||||||
|
[localTZ methodForSelector: abrSEL];
|
||||||
|
dstAbrIMP = (NSString* (*)(id,SEL,id))
|
||||||
|
[dstClass instanceMethodForSelector: abrSEL];
|
||||||
|
absAbrIMP = (NSString* (*)(id,SEL,id))
|
||||||
|
[absClass instanceMethodForSelector: abrSEL];
|
||||||
|
|
||||||
behavior_class_add_class(self, [NSGDate class]);
|
behavior_class_add_class(self, [NSGDate class]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1081,19 +1174,19 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
/*
|
/*
|
||||||
* Adjust date so it is correct for time zone.
|
* Adjust date so it is correct for time zone.
|
||||||
*/
|
*/
|
||||||
oldOffset = [_time_zone secondsFromGMTForDate: self];
|
oldOffset = offset(_time_zone, self);
|
||||||
s -= oldOffset;
|
s -= oldOffset;
|
||||||
_seconds_since_ref = s;
|
_seconds_since_ref = s;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if we need to adjust for daylight savings time
|
* See if we need to adjust for daylight savings time
|
||||||
*/
|
*/
|
||||||
newOffset = [_time_zone secondsFromGMTForDate: self];
|
newOffset = offset(_time_zone, self);
|
||||||
if (oldOffset != newOffset)
|
if (oldOffset != newOffset)
|
||||||
{
|
{
|
||||||
s -= (newOffset - oldOffset);
|
s -= (newOffset - oldOffset);
|
||||||
_seconds_since_ref = s;
|
_seconds_since_ref = s;
|
||||||
oldOffset = [_time_zone secondsFromGMTForDate: self];
|
oldOffset = offset(_time_zone, self);
|
||||||
/*
|
/*
|
||||||
* If the adjustment puts us in another offset, we must be in the
|
* If the adjustment puts us in another offset, we must be in the
|
||||||
* non-existent period at the start of daylight savings time.
|
* non-existent period at the start of daylight savings time.
|
||||||
|
@ -1130,7 +1223,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
{
|
{
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
return dayOfCommonEra(when);
|
return dayOfCommonEra(when);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1139,7 +1232,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
int m, d, y;
|
int m, d, y;
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
gregorianDateFromAbsolute(dayOfCommonEra(when), &d, &m, &y);
|
gregorianDateFromAbsolute(dayOfCommonEra(when), &d, &m, &y);
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
|
@ -1150,7 +1243,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
int d;
|
int d;
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
d = dayOfCommonEra(when);
|
d = dayOfCommonEra(when);
|
||||||
|
|
||||||
/* The era started on a sunday.
|
/* The era started on a sunday.
|
||||||
|
@ -1168,7 +1261,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
int m, d, y, days, i;
|
int m, d, y, days, i;
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
gregorianDateFromAbsolute(dayOfCommonEra(when), &d, &m, &y);
|
gregorianDateFromAbsolute(dayOfCommonEra(when), &d, &m, &y);
|
||||||
days = d;
|
days = d;
|
||||||
for (i = m - 1; i > 0; i--) // days in prior months this year
|
for (i = m - 1; i > 0; i--) // days in prior months this year
|
||||||
|
@ -1183,11 +1276,11 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
double a, d;
|
double a, d;
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
d = dayOfCommonEra(when);
|
d = dayOfCommonEra(when);
|
||||||
d -= GREGORIAN_REFERENCE;
|
d -= GREGORIAN_REFERENCE;
|
||||||
d *= 86400;
|
d *= 86400;
|
||||||
a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self]));
|
a = abs(d - (_seconds_since_ref + offset(_time_zone, self)));
|
||||||
a = a / 3600;
|
a = a / 3600;
|
||||||
h = (int)a;
|
h = (int)a;
|
||||||
|
|
||||||
|
@ -1205,11 +1298,11 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
double a, b, d;
|
double a, b, d;
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
d = dayOfCommonEra(when);
|
d = dayOfCommonEra(when);
|
||||||
d -= GREGORIAN_REFERENCE;
|
d -= GREGORIAN_REFERENCE;
|
||||||
d *= 86400;
|
d *= 86400;
|
||||||
a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self]));
|
a = abs(d - (_seconds_since_ref + offset(_time_zone, self)));
|
||||||
b = a / 3600;
|
b = a / 3600;
|
||||||
h = (int)b;
|
h = (int)b;
|
||||||
h = h * 3600;
|
h = h * 3600;
|
||||||
|
@ -1225,7 +1318,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
int m, d, y;
|
int m, d, y;
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
gregorianDateFromAbsolute(dayOfCommonEra(when), &d, &m, &y);
|
gregorianDateFromAbsolute(dayOfCommonEra(when), &d, &m, &y);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
@ -1237,11 +1330,11 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
double a, b, c, d;
|
double a, b, c, d;
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
d = dayOfCommonEra(when);
|
d = dayOfCommonEra(when);
|
||||||
d -= GREGORIAN_REFERENCE;
|
d -= GREGORIAN_REFERENCE;
|
||||||
d *= 86400;
|
d *= 86400;
|
||||||
a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self]));
|
a = abs(d - (_seconds_since_ref + offset(_time_zone, self)));
|
||||||
b = a / 3600;
|
b = a / 3600;
|
||||||
h = (int)b;
|
h = (int)b;
|
||||||
h = h * 3600;
|
h = h * 3600;
|
||||||
|
@ -1260,7 +1353,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
int m, d, y;
|
int m, d, y;
|
||||||
NSTimeInterval when;
|
NSTimeInterval when;
|
||||||
|
|
||||||
when = _seconds_since_ref+[_time_zone secondsFromGMTForDate: self];
|
when = _seconds_since_ref + offset(_time_zone, self);
|
||||||
gregorianDateFromAbsolute(dayOfCommonEra(when), &d, &m, &y);
|
gregorianDateFromAbsolute(dayOfCommonEra(when), &d, &m, &y);
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
|
@ -1319,7 +1412,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
f = [format cString];
|
f = [format cString];
|
||||||
lf = strlen(f);
|
lf = strlen(f);
|
||||||
|
|
||||||
GSBreakTime(_seconds_since_ref + [_time_zone secondsFromGMTForDate: self],
|
GSBreakTime(_seconds_since_ref + offset(_time_zone, self),
|
||||||
&yd, &md, &dom, &hd, &mnd, &sd, &mil);
|
&yd, &md, &dom, &hd, &mnd, &sd, &mil);
|
||||||
nhd = hd;
|
nhd = hd;
|
||||||
|
|
||||||
|
@ -1419,8 +1512,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
|
|
||||||
case 'F': // milliseconds
|
case 'F': // milliseconds
|
||||||
s = ([self dayOfCommonEra] - GREGORIAN_REFERENCE) * 86400.0;
|
s = ([self dayOfCommonEra] - GREGORIAN_REFERENCE) * 86400.0;
|
||||||
s -= (_seconds_since_ref
|
s -= (_seconds_since_ref + offset(_time_zone, self));
|
||||||
+ [_time_zone secondsFromGMTForDate: self]);
|
|
||||||
s = fabs(s);
|
s = fabs(s);
|
||||||
s -= floor(s);
|
s -= floor(s);
|
||||||
++i;
|
++i;
|
||||||
|
@ -1521,13 +1613,13 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
case 'Z':
|
case 'Z':
|
||||||
++i;
|
++i;
|
||||||
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s",
|
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s",
|
||||||
[[_time_zone abbreviationForDate: self] cString]));
|
[abbrev(_time_zone, self) UTF8String]));
|
||||||
j += k;
|
j += k;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'z':
|
case 'z':
|
||||||
++i;
|
++i;
|
||||||
z = [_time_zone secondsFromGMTForDate: self];
|
z = offset(_time_zone, self);
|
||||||
if (z < 0) {
|
if (z < 0) {
|
||||||
z = -z;
|
z = -z;
|
||||||
z /= 60;
|
z /= 60;
|
||||||
|
@ -1675,7 +1767,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
NSTimeInterval newOffset;
|
NSTimeInterval newOffset;
|
||||||
int i, year, month, day, hour, minute, second, mil;
|
int i, year, month, day, hour, minute, second, mil;
|
||||||
|
|
||||||
oldOffset = [_time_zone secondsFromGMTForDate: self];
|
oldOffset = offset(_time_zone, self);
|
||||||
/*
|
/*
|
||||||
* Break into components in GMT time zone.
|
* Break into components in GMT time zone.
|
||||||
*/
|
*/
|
||||||
|
@ -1782,7 +1874,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
* Adjust date to try to maintain the time of day over
|
* Adjust date to try to maintain the time of day over
|
||||||
* a daylight savings time boundary if necessary.
|
* a daylight savings time boundary if necessary.
|
||||||
*/
|
*/
|
||||||
newOffset = [_time_zone secondsFromGMTForDate: c];
|
newOffset = offset(_time_zone, c);
|
||||||
if (newOffset != oldOffset)
|
if (newOffset != oldOffset)
|
||||||
{
|
{
|
||||||
NSTimeInterval tmpOffset = newOffset;
|
NSTimeInterval tmpOffset = newOffset;
|
||||||
|
@ -1794,7 +1886,7 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
* daylight savings time transition, we use the original
|
* daylight savings time transition, we use the original
|
||||||
* date rather than the adjusted one.
|
* date rather than the adjusted one.
|
||||||
*/
|
*/
|
||||||
newOffset = [_time_zone secondsFromGMTForDate: c];
|
newOffset = offset(_time_zone, c);
|
||||||
if (newOffset == oldOffset)
|
if (newOffset == oldOffset)
|
||||||
{
|
{
|
||||||
s += (tmpOffset - oldOffset);
|
s += (tmpOffset - oldOffset);
|
||||||
|
@ -1846,12 +1938,10 @@ static inline int getDigits(const char *from, char *to, int limit)
|
||||||
sign = -1;
|
sign = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSBreakTime(start->_seconds_since_ref
|
GSBreakTime(start->_seconds_since_ref + offset(start->_time_zone, start),
|
||||||
+ [start->_time_zone secondsFromGMTForDate: start],
|
|
||||||
&syear, &smonth, &sday, &shour, &sminute, &ssecond, &mil);
|
&syear, &smonth, &sday, &shour, &sminute, &ssecond, &mil);
|
||||||
|
|
||||||
GSBreakTime(end->_seconds_since_ref
|
GSBreakTime(end->_seconds_since_ref + offset(end->_time_zone, end),
|
||||||
+ [end->_time_zone secondsFromGMTForDate: end],
|
|
||||||
&eyear, &emonth, &eday, &ehour, &eminute, &esecond, &mil);
|
&eyear, &emonth, &eday, &ehour, &eminute, &esecond, &mil);
|
||||||
|
|
||||||
/* Calculate year difference and leave any remaining months in 'extra' */
|
/* Calculate year difference and leave any remaining months in 'extra' */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue