Skip to content

Commit

Permalink
Tweaks to NSDate changes
Browse files Browse the repository at this point in the history
  • Loading branch information
rfm committed Nov 1, 2024
1 parent 9978c05 commit 962c169
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 78 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2024-11-01 Richard Frith-Macdonald <[email protected]>

* Source/NSDate.m: Fix returing receiver when earlier/later argument
is equal to the receiver. Various formatting fixes.

2024-10-29 Richard Frith-Macdonald <[email protected]>

* Source/NSUndoManager.m: set zero/nil return value when forwarding
Expand Down
186 changes: 108 additions & 78 deletions Source/NSDate.m
Original file line number Diff line number Diff line change
Expand Up @@ -140,70 +140,74 @@
#define CREATE_SMALL_DATE(interval) (id)(compressTimeInterval(interval) | SMALL_DATE_MASK)

union CompressedDouble {
uintptr_t data;
struct {
uintptr_t tag : 3; // placeholder for tag bits
uintptr_t fraction : 52;
intptr_t exponent : 8; // signed!
uintptr_t sign : 1;
};
uintptr_t data;
struct {
uintptr_t tag : 3; // placeholder for tag bits
uintptr_t fraction : 52;
intptr_t exponent : 8; // signed!
uintptr_t sign : 1;
};
};

union DoubleBits {
double val;
struct {
uintptr_t fraction : 52;
uintptr_t exponent : 11;
uintptr_t sign : 1;
};
double val;
struct {
uintptr_t fraction : 52;
uintptr_t exponent : 11;
uintptr_t sign : 1;
};
};

static __attribute__((always_inline)) uintptr_t compressTimeInterval(NSTimeInterval interval) {
union CompressedDouble c;
union DoubleBits db;
intptr_t exponent;
static __attribute__((always_inline)) uintptr_t
compressTimeInterval(NSTimeInterval interval)
{
union CompressedDouble c;
union DoubleBits db;
intptr_t exponent;

db.val = interval;
c.fraction = db.fraction;
c.sign = db.sign;
db.val = interval;
c.fraction = db.fraction;
c.sign = db.sign;

// 1. Cast 11-bit unsigned exponent to 64-bit signed
exponent = db.exponent;
// 2. Subtract secondary Bias first
exponent -= EXPONENT_BIAS;
// 3. Truncate to 8-bit signed
c.exponent = exponent;
c.tag = 0;
// 1. Cast 11-bit unsigned exponent to 64-bit signed
exponent = db.exponent;
// 2. Subtract secondary Bias first
exponent -= EXPONENT_BIAS;
// 3. Truncate to 8-bit signed
c.exponent = exponent;
c.tag = 0;

return c.data;
return c.data;
}

static __attribute__((always_inline)) NSTimeInterval decompressTimeInterval(uintptr_t compressed) {
union CompressedDouble c;
union DoubleBits d;
intptr_t biased_exponent;
static __attribute__((always_inline)) NSTimeInterval
decompressTimeInterval(uintptr_t compressed)
{
union CompressedDouble c;
union DoubleBits d;
intptr_t biased_exponent;

c.data = compressed;
d.fraction = c.fraction;
d.sign = c.sign;
c.data = compressed;
d.fraction = c.fraction;
d.sign = c.sign;

// 1. Sign Extend 8-bit to 64-bit
biased_exponent = c.exponent;
// 2. Add secondary Bias
biased_exponent += 0x3EF;
// Cast to 11-bit unsigned exponent
d.exponent = biased_exponent;
// 1. Sign Extend 8-bit to 64-bit
biased_exponent = c.exponent;
// 2. Add secondary Bias
biased_exponent += 0x3EF;
// Cast to 11-bit unsigned exponent
d.exponent = biased_exponent;

return d.val;
return d.val;
}

static __attribute__((always_inline)) BOOL isSmallDate(id obj) {
// Do a fast check if the object is also a small date.
// libobjc2 guarantees that the classes are 16-byte (word) aligned.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-objc-pointer-introspection"
return !!((uintptr_t)obj & SMALL_DATE_MASK);
#pragma clang diagnostic pop
// Do a fast check if the object is also a small date.
// libobjc2 guarantees that the classes are 16-byte (word) aligned.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-objc-pointer-introspection"
return !!((uintptr_t)obj & SMALL_DATE_MASK);
#pragma clang diagnostic pop
}

// Populated in +[GSSmallDate load]
Expand Down Expand Up @@ -234,10 +238,13 @@ @implementation DATE_CONCRETE_CLASS_NAME
+ (void) load
{
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))
{
[NSException raise: NSInternalInconsistencyException format: @"Failed to register GSSmallDate small object class"];
[NSException raise: NSInternalInconsistencyException
format: @"Failed to register GSSmallDate small object class"];
}
}

Expand Down Expand Up @@ -349,6 +356,7 @@ - (id) initWithTimeIntervalSinceReferenceDate: (NSTimeInterval)secs
- (id) initWithCoder: (NSCoder*)coder
{
double secondsSinceRef;

if ([coder allowsKeyedCoding])
{
secondsSinceRef = [coder decodeDoubleForKey: @"NS.time"];
Expand Down Expand Up @@ -394,11 +402,13 @@ - (NSComparisonResult) compare: (NSDate*)otherDate
}

if (IS_CONCRETE_CLASS(otherDate))
{
{
otherTime = GET_INTERVAL(otherDate);
} else {
}
else
{
otherTime = [otherDate timeIntervalSinceReferenceDate];
}
}

if (selfTime > otherTime)
{
Expand All @@ -422,14 +432,17 @@ - (BOOL) isEqual: (id)other
}

if (IS_CONCRETE_CLASS(other))
{
{
otherTime = GET_INTERVAL(other);
} else if ([other isKindOfClass: abstractClass])
{
}
else if ([other isKindOfClass: abstractClass])
{
otherTime = [other timeIntervalSinceReferenceDate];
} else {
return NO;
}
}
else
{
return NO;
}

return selfTime == otherTime;
}
Expand All @@ -452,14 +465,18 @@ - (NSDate*) laterDate: (NSDate*)otherDate

selfTime = GET_INTERVAL(self);
if (IS_CONCRETE_CLASS(otherDate))
{
{
otherTime = GET_INTERVAL(otherDate);
} else {
}
else
{
otherTime = [otherDate timeIntervalSinceReferenceDate];
}
}

// If the receiver and anotherDate represent the same date, returns the receiver.
if (selfTime <= otherTime)
/* If the receiver and anotherDate represent the same date,
* returns the receiver.
*/
if (selfTime < otherTime)
{
return otherDate;
}
Expand All @@ -480,14 +497,18 @@ - (NSDate*) earlierDate: (NSDate*)otherDate

selfTime = GET_INTERVAL(self);
if (IS_CONCRETE_CLASS(otherDate))
{
{
otherTime = GET_INTERVAL(otherDate);
} else {
}
else
{
otherTime = [otherDate timeIntervalSinceReferenceDate];
}
}

// If the receiver and anotherDate represent the same date, returns the receiver.
if (selfTime >= otherTime)
/* If the receiver and anotherDate represent the same date,
* returns the receiver.
*/
if (selfTime > otherTime)
{
return otherDate;
}
Expand All @@ -498,9 +519,10 @@ - (NSDate*) earlierDate: (NSDate*)otherDate
- (void) encodeWithCoder: (NSCoder*)coder
{
double time = GET_INTERVAL(self);

if ([coder allowsKeyedCoding])
{
[coder encodeDouble:time forKey:@"NS.time"];
[coder encodeDouble: time forKey:@"NS.time"];
}
else
{
Expand All @@ -519,18 +541,21 @@ - (NSTimeInterval) timeIntervalSince1970
- (NSTimeInterval) timeIntervalSinceDate: (NSDate*)otherDate
{
double otherTime;

if (unlikely(otherDate == nil))
{
[NSException raise: NSInvalidArgumentException
format: @"nil argument for timeIntervalSinceDate:"];
}

if (IS_CONCRETE_CLASS(otherDate))
{
{
otherTime = GET_INTERVAL(otherDate);
} else {
}
else
{
otherTime = [otherDate timeIntervalSinceReferenceDate];
}
}

return GET_INTERVAL(self) - otherTime;
}
Expand Down Expand Up @@ -700,7 +725,9 @@ + (id) alloc
if (self == abstractClass)
{
#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
return NSAllocateObject(concreteClass, 0, NSDefaultMallocZone());
#endif
Expand All @@ -713,7 +740,9 @@ + (id) allocWithZone: (NSZone*)z
if (self == abstractClass)
{
#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
return NSAllocateObject(concreteClass, 0, z);
#endif
Expand Down Expand Up @@ -1784,10 +1813,11 @@ - (BOOL) isEqualToDate: (NSDate*)other
- (NSDate*) laterDate: (NSDate*)otherDate
{
double selfTime;

if (otherDate == nil)
{
return nil;
}
{
return nil;
}

selfTime = [self timeIntervalSinceReferenceDate];
if (selfTime < otherTime(otherDate))
Expand Down

0 comments on commit 962c169

Please sign in to comment.