mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
Tweaks to NSDate changes
This commit is contained in:
parent
7a59450341
commit
d0bff27c77
2 changed files with 113 additions and 78 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2024-11-01 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/NSDate.m: Fix returing receiver when earlier/later argument
|
||||||
|
is equal to the receiver. Various formatting fixes.
|
||||||
|
|
||||||
2024-10-29 Richard Frith-Macdonald <rfm@gnu.org>
|
2024-10-29 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/NSUndoManager.m: set zero/nil return value when forwarding
|
* Source/NSUndoManager.m: set zero/nil return value when forwarding
|
||||||
|
|
186
Source/NSDate.m
186
Source/NSDate.m
|
@ -140,70 +140,74 @@ static id _distantFuture = nil;
|
||||||
#define CREATE_SMALL_DATE(interval) (id)(compressTimeInterval(interval) | SMALL_DATE_MASK)
|
#define CREATE_SMALL_DATE(interval) (id)(compressTimeInterval(interval) | SMALL_DATE_MASK)
|
||||||
|
|
||||||
union CompressedDouble {
|
union CompressedDouble {
|
||||||
uintptr_t data;
|
uintptr_t data;
|
||||||
struct {
|
struct {
|
||||||
uintptr_t tag : 3; // placeholder for tag bits
|
uintptr_t tag : 3; // placeholder for tag bits
|
||||||
uintptr_t fraction : 52;
|
uintptr_t fraction : 52;
|
||||||
intptr_t exponent : 8; // signed!
|
intptr_t exponent : 8; // signed!
|
||||||
uintptr_t sign : 1;
|
uintptr_t sign : 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
union DoubleBits {
|
union DoubleBits {
|
||||||
double val;
|
double val;
|
||||||
struct {
|
struct {
|
||||||
uintptr_t fraction : 52;
|
uintptr_t fraction : 52;
|
||||||
uintptr_t exponent : 11;
|
uintptr_t exponent : 11;
|
||||||
uintptr_t sign : 1;
|
uintptr_t sign : 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
static __attribute__((always_inline)) uintptr_t compressTimeInterval(NSTimeInterval interval) {
|
static __attribute__((always_inline)) uintptr_t
|
||||||
union CompressedDouble c;
|
compressTimeInterval(NSTimeInterval interval)
|
||||||
union DoubleBits db;
|
{
|
||||||
intptr_t exponent;
|
union CompressedDouble c;
|
||||||
|
union DoubleBits db;
|
||||||
|
intptr_t exponent;
|
||||||
|
|
||||||
db.val = interval;
|
db.val = interval;
|
||||||
c.fraction = db.fraction;
|
c.fraction = db.fraction;
|
||||||
c.sign = db.sign;
|
c.sign = db.sign;
|
||||||
|
|
||||||
// 1. Cast 11-bit unsigned exponent to 64-bit signed
|
// 1. Cast 11-bit unsigned exponent to 64-bit signed
|
||||||
exponent = db.exponent;
|
exponent = db.exponent;
|
||||||
// 2. Subtract secondary Bias first
|
// 2. Subtract secondary Bias first
|
||||||
exponent -= EXPONENT_BIAS;
|
exponent -= EXPONENT_BIAS;
|
||||||
// 3. Truncate to 8-bit signed
|
// 3. Truncate to 8-bit signed
|
||||||
c.exponent = exponent;
|
c.exponent = exponent;
|
||||||
c.tag = 0;
|
c.tag = 0;
|
||||||
|
|
||||||
return c.data;
|
return c.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((always_inline)) NSTimeInterval decompressTimeInterval(uintptr_t compressed) {
|
static __attribute__((always_inline)) NSTimeInterval
|
||||||
union CompressedDouble c;
|
decompressTimeInterval(uintptr_t compressed)
|
||||||
union DoubleBits d;
|
{
|
||||||
intptr_t biased_exponent;
|
union CompressedDouble c;
|
||||||
|
union DoubleBits d;
|
||||||
|
intptr_t biased_exponent;
|
||||||
|
|
||||||
c.data = compressed;
|
c.data = compressed;
|
||||||
d.fraction = c.fraction;
|
d.fraction = c.fraction;
|
||||||
d.sign = c.sign;
|
d.sign = c.sign;
|
||||||
|
|
||||||
// 1. Sign Extend 8-bit to 64-bit
|
// 1. Sign Extend 8-bit to 64-bit
|
||||||
biased_exponent = c.exponent;
|
biased_exponent = c.exponent;
|
||||||
// 2. Add secondary Bias
|
// 2. Add secondary Bias
|
||||||
biased_exponent += 0x3EF;
|
biased_exponent += 0x3EF;
|
||||||
// Cast to 11-bit unsigned exponent
|
// Cast to 11-bit unsigned exponent
|
||||||
d.exponent = biased_exponent;
|
d.exponent = biased_exponent;
|
||||||
|
|
||||||
return d.val;
|
return d.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((always_inline)) BOOL isSmallDate(id obj) {
|
static __attribute__((always_inline)) BOOL isSmallDate(id obj) {
|
||||||
// Do a fast check if the object is also a small date.
|
// Do a fast check if the object is also a small date.
|
||||||
// libobjc2 guarantees that the classes are 16-byte (word) aligned.
|
// libobjc2 guarantees that the classes are 16-byte (word) aligned.
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-objc-pointer-introspection"
|
#pragma clang diagnostic ignored "-Wdeprecated-objc-pointer-introspection"
|
||||||
return !!((uintptr_t)obj & SMALL_DATE_MASK);
|
return !!((uintptr_t)obj & SMALL_DATE_MASK);
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populated in +[GSSmallDate load]
|
// Populated in +[GSSmallDate load]
|
||||||
|
@ -234,10 +238,13 @@ static BOOL useSmallDate;
|
||||||
+ (void) load
|
+ (void) load
|
||||||
{
|
{
|
||||||
useSmallDate = objc_registerSmallObjectClass_np(self, SMALL_DATE_MASK);
|
useSmallDate = objc_registerSmallObjectClass_np(self, SMALL_DATE_MASK);
|
||||||
// If this fails, someone else has already registered a small object class for this slot.
|
/* If this fails, someone else has already registered
|
||||||
|
* a small object class for this slot.
|
||||||
|
*/
|
||||||
if (unlikely(useSmallDate == NO))
|
if (unlikely(useSmallDate == NO))
|
||||||
{
|
{
|
||||||
[NSException raise: NSInternalInconsistencyException format: @"Failed to register GSSmallDate small object class"];
|
[NSException raise: NSInternalInconsistencyException
|
||||||
|
format: @"Failed to register GSSmallDate small object class"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,6 +356,7 @@ static BOOL useSmallDate;
|
||||||
- (id) initWithCoder: (NSCoder*)coder
|
- (id) initWithCoder: (NSCoder*)coder
|
||||||
{
|
{
|
||||||
double secondsSinceRef;
|
double secondsSinceRef;
|
||||||
|
|
||||||
if ([coder allowsKeyedCoding])
|
if ([coder allowsKeyedCoding])
|
||||||
{
|
{
|
||||||
secondsSinceRef = [coder decodeDoubleForKey: @"NS.time"];
|
secondsSinceRef = [coder decodeDoubleForKey: @"NS.time"];
|
||||||
|
@ -394,11 +402,13 @@ static BOOL useSmallDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_CONCRETE_CLASS(otherDate))
|
if (IS_CONCRETE_CLASS(otherDate))
|
||||||
{
|
{
|
||||||
otherTime = GET_INTERVAL(otherDate);
|
otherTime = GET_INTERVAL(otherDate);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
otherTime = [otherDate timeIntervalSinceReferenceDate];
|
otherTime = [otherDate timeIntervalSinceReferenceDate];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selfTime > otherTime)
|
if (selfTime > otherTime)
|
||||||
{
|
{
|
||||||
|
@ -422,14 +432,17 @@ static BOOL useSmallDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_CONCRETE_CLASS(other))
|
if (IS_CONCRETE_CLASS(other))
|
||||||
{
|
{
|
||||||
otherTime = GET_INTERVAL(other);
|
otherTime = GET_INTERVAL(other);
|
||||||
} else if ([other isKindOfClass: abstractClass])
|
}
|
||||||
{
|
else if ([other isKindOfClass: abstractClass])
|
||||||
|
{
|
||||||
otherTime = [other timeIntervalSinceReferenceDate];
|
otherTime = [other timeIntervalSinceReferenceDate];
|
||||||
} else {
|
}
|
||||||
return NO;
|
else
|
||||||
}
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
return selfTime == otherTime;
|
return selfTime == otherTime;
|
||||||
}
|
}
|
||||||
|
@ -452,14 +465,18 @@ static BOOL useSmallDate;
|
||||||
|
|
||||||
selfTime = GET_INTERVAL(self);
|
selfTime = GET_INTERVAL(self);
|
||||||
if (IS_CONCRETE_CLASS(otherDate))
|
if (IS_CONCRETE_CLASS(otherDate))
|
||||||
{
|
{
|
||||||
otherTime = GET_INTERVAL(otherDate);
|
otherTime = GET_INTERVAL(otherDate);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
otherTime = [otherDate timeIntervalSinceReferenceDate];
|
otherTime = [otherDate timeIntervalSinceReferenceDate];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the receiver and anotherDate represent the same date, returns the receiver.
|
/* If the receiver and anotherDate represent the same date,
|
||||||
if (selfTime <= otherTime)
|
* returns the receiver.
|
||||||
|
*/
|
||||||
|
if (selfTime < otherTime)
|
||||||
{
|
{
|
||||||
return otherDate;
|
return otherDate;
|
||||||
}
|
}
|
||||||
|
@ -480,14 +497,18 @@ static BOOL useSmallDate;
|
||||||
|
|
||||||
selfTime = GET_INTERVAL(self);
|
selfTime = GET_INTERVAL(self);
|
||||||
if (IS_CONCRETE_CLASS(otherDate))
|
if (IS_CONCRETE_CLASS(otherDate))
|
||||||
{
|
{
|
||||||
otherTime = GET_INTERVAL(otherDate);
|
otherTime = GET_INTERVAL(otherDate);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
otherTime = [otherDate timeIntervalSinceReferenceDate];
|
otherTime = [otherDate timeIntervalSinceReferenceDate];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the receiver and anotherDate represent the same date, returns the receiver.
|
/* If the receiver and anotherDate represent the same date,
|
||||||
if (selfTime >= otherTime)
|
* returns the receiver.
|
||||||
|
*/
|
||||||
|
if (selfTime > otherTime)
|
||||||
{
|
{
|
||||||
return otherDate;
|
return otherDate;
|
||||||
}
|
}
|
||||||
|
@ -498,9 +519,10 @@ static BOOL useSmallDate;
|
||||||
- (void) encodeWithCoder: (NSCoder*)coder
|
- (void) encodeWithCoder: (NSCoder*)coder
|
||||||
{
|
{
|
||||||
double time = GET_INTERVAL(self);
|
double time = GET_INTERVAL(self);
|
||||||
|
|
||||||
if ([coder allowsKeyedCoding])
|
if ([coder allowsKeyedCoding])
|
||||||
{
|
{
|
||||||
[coder encodeDouble:time forKey:@"NS.time"];
|
[coder encodeDouble: time forKey:@"NS.time"];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -519,6 +541,7 @@ static BOOL useSmallDate;
|
||||||
- (NSTimeInterval) timeIntervalSinceDate: (NSDate*)otherDate
|
- (NSTimeInterval) timeIntervalSinceDate: (NSDate*)otherDate
|
||||||
{
|
{
|
||||||
double otherTime;
|
double otherTime;
|
||||||
|
|
||||||
if (unlikely(otherDate == nil))
|
if (unlikely(otherDate == nil))
|
||||||
{
|
{
|
||||||
[NSException raise: NSInvalidArgumentException
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
@ -526,11 +549,13 @@ static BOOL useSmallDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_CONCRETE_CLASS(otherDate))
|
if (IS_CONCRETE_CLASS(otherDate))
|
||||||
{
|
{
|
||||||
otherTime = GET_INTERVAL(otherDate);
|
otherTime = GET_INTERVAL(otherDate);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
otherTime = [otherDate timeIntervalSinceReferenceDate];
|
otherTime = [otherDate timeIntervalSinceReferenceDate];
|
||||||
}
|
}
|
||||||
|
|
||||||
return GET_INTERVAL(self) - otherTime;
|
return GET_INTERVAL(self) - otherTime;
|
||||||
}
|
}
|
||||||
|
@ -700,7 +725,9 @@ otherTime(NSDate* other)
|
||||||
if (self == abstractClass)
|
if (self == abstractClass)
|
||||||
{
|
{
|
||||||
#if USE_SMALL_DATE
|
#if USE_SMALL_DATE
|
||||||
return [DATE_CONCRETE_CLASS_NAME alloc]; // alloc is overridden to return a small object
|
/* alloc is overridden to return a small object
|
||||||
|
*/
|
||||||
|
return [DATE_CONCRETE_CLASS_NAME alloc];
|
||||||
#else
|
#else
|
||||||
return NSAllocateObject(concreteClass, 0, NSDefaultMallocZone());
|
return NSAllocateObject(concreteClass, 0, NSDefaultMallocZone());
|
||||||
#endif
|
#endif
|
||||||
|
@ -713,7 +740,9 @@ otherTime(NSDate* other)
|
||||||
if (self == abstractClass)
|
if (self == abstractClass)
|
||||||
{
|
{
|
||||||
#if USE_SMALL_DATE
|
#if USE_SMALL_DATE
|
||||||
return [DATE_CONCRETE_CLASS_NAME alloc]; // alloc is overridden to return a small object
|
/* alloc is overridden to return a small object
|
||||||
|
*/
|
||||||
|
return [DATE_CONCRETE_CLASS_NAME alloc];
|
||||||
#else
|
#else
|
||||||
return NSAllocateObject(concreteClass, 0, z);
|
return NSAllocateObject(concreteClass, 0, z);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1784,10 +1813,11 @@ otherTime(NSDate* other)
|
||||||
- (NSDate*) laterDate: (NSDate*)otherDate
|
- (NSDate*) laterDate: (NSDate*)otherDate
|
||||||
{
|
{
|
||||||
double selfTime;
|
double selfTime;
|
||||||
|
|
||||||
if (otherDate == nil)
|
if (otherDate == nil)
|
||||||
{
|
{
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
selfTime = [self timeIntervalSinceReferenceDate];
|
selfTime = [self timeIntervalSinceReferenceDate];
|
||||||
if (selfTime < otherTime(otherDate))
|
if (selfTime < otherTime(otherDate))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue