Files
cappuccino/Foundation/CPNumber.j
T
David Richardson f414fae60a Replace tabs with spaces
Tab indentation inadvertenly applied previously.
2026-08-04 18:09:27 -06:00

356 lines
7.3 KiB
Plaintext

/*
* CPNumber.j
* Foundation
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPException.j"
@import "CPNull.j"
@import "CPObject.j"
@import "CPObjJRuntime.j"
// MODIFICATION: Added FIXME to highlight global mutable state anti-pattern.
// FIXME: Anti-pattern: Global Mutable State. This dictionary tracks UIDs for primitives
// and grows indefinitely in long-running processes, causing memory leaks.
const CPNumberUIDs = new CFMutableDictionary();
/*!
@class CPNumber
@ingroup foundation
@brief A bridged object to native Javascript numbers.
*/
@implementation CPNumber : CPObject
+ (id)alloc
{
// MODIFICATION: Replaced 'var' with 'let' for block scoping.
let result = new Number();
result.isa = [self class];
return result;
}
+ (id)numberWithBool:(BOOL)aBoolean
{
return aBoolean ? 1 : 0;
}
+ (id)numberWithChar:(char)aChar
{
if (aChar.charCodeAt)
return aChar.charCodeAt(0);
return aChar;
}
+ (id)numberWithDouble:(double)aDouble
{
return aDouble;
}
+ (id)numberWithFloat:(float)aFloat
{
return aFloat;
}
+ (id)numberWithInt:(int)anInt
{
return anInt;
}
+ (id)numberWithLong:(long)aLong
{
return aLong;
}
+ (id)numberWithLongLong:(long long)aLongLong
{
return aLongLong;
}
+ (id)numberWithShort:(short)aShort
{
return aShort;
}
+ (id)numberWithUnsignedChar:(unsigned char)aChar
{
if (aChar.charCodeAt)
return aChar.charCodeAt(0);
return aChar;
}
+ (id)numberWithUnsignedInt:(unsigned)anUnsignedInt
{
return anUnsignedInt;
}
+ (id)numberWithUnsignedLong:(unsigned long)anUnsignedLong
{
return anUnsignedLong;
}
+ (id)numberWithUnsignedShort:(unsigned short)anUnsignedShort
{
return anUnsignedShort;
}
- (id)initWithBool:(BOOL)aBoolean
{
return aBoolean;
}
- (id)initWithChar:(char)aChar
{
if (aChar.charCodeAt)
return aChar.charCodeAt(0);
return aChar;
}
- (id)initWithDouble:(double)aDouble
{
return aDouble;
}
- (id)initWithFloat:(float)aFloat
{
return aFloat;
}
- (id)initWithInt:(int)anInt
{
return anInt;
}
- (id)initWithLong:(long)aLong
{
return aLong;
}
- (id)initWithLongLong:(long long)aLongLong
{
return aLongLong;
}
- (id)initWithShort:(short)aShort
{
return aShort;
}
- (id)initWithUnsignedChar:(unsigned char)aChar
{
if (aChar.charCodeAt)
return aChar.charCodeAt(0);
return aChar;
}
- (id)initWithUnsignedInt:(unsigned)anUnsignedInt
{
return anUnsignedInt;
}
- (id)initWithUnsignedLong:(unsigned long)anUnsignedLong
{
return anUnsignedLong;
}
- (id)initWithUnsignedShort:(unsigned short)anUnsignedShort
{
return anUnsignedShort;
}
- (CPString)UID
{
// MODIFICATION: Replaced 'var' with 'let' for block scoping.
let UID = CPNumberUIDs.valueForKey(self);
if (!UID)
{
UID = objj_generateObjectUID();
CPNumberUIDs.setValueForKey(self, UID);
}
return UID + "";
}
- (BOOL)boolValue
{
// MODIFICATION: Replaced conditional logic with double-not operator for strict boolean coercion.
return !!self;
}
// MODIFICATION: Added FIXME to highlight unimplemented feature.
// FIXME: Unimplemented Feature. CPDecimal is not natively supported.
// This should either be removed or throw a proper CPInvalidArgumentException.
- (CPDecimal)decimalValue
{
throw new Error("decimalValue: NOT YET IMPLEMENTED");
}
- (CPString)descriptionWithLocale:(CPDictionary)aDictionary
{
// MODIFICATION: Removed hostile runtime Error throw. Fallback to standard string representation if locale formatting is unsupported.
return self.toString();
}
- (CPString)description
{
return [self descriptionWithLocale:nil];
}
- (double)doubleValue
{
if (typeof self == "boolean")
return self ? 1 : 0;
return self;
}
- (float)floatValue
{
if (typeof self == "boolean")
return self ? 1 : 0;
return self;
}
- (int)intValue
{
// MODIFICATION: Removed CAST_TO_INT macro, replaced with native ES6 Math.trunc().
return Math.trunc(self);
}
- (int)integerValue
{
// MODIFICATION: Removed CAST_TO_INT macro, replaced with native ES6 Math.trunc().
return Math.trunc(self);
}
- (long long)longLongValue
{
// MODIFICATION: Removed CAST_TO_INT macro, replaced with native ES6 Math.trunc().
return Math.trunc(self);
}
- (long)longValue
{
// MODIFICATION: Removed CAST_TO_INT macro, replaced with native ES6 Math.trunc().
return Math.trunc(self);
}
- (short)shortValue
{
// MODIFICATION: Removed CAST_TO_INT macro, replaced with native ES6 Math.trunc().
return Math.trunc(self);
}
- (CPString)stringValue
{
return self.toString();
}
- (unsigned char)unsignedCharValue
{
return String.fromCharCode(self);
}
- (unsigned int)unsignedIntValue
{
// Despite the name this method does not make a negative value positive in Objective-C, so neither does it here.
// MODIFICATION: Removed CAST_TO_INT macro, replaced with native ES6 Math.trunc().
return Math.trunc(self);
}
- (unsigned long)unsignedLongValue
{
// Despite the name this method does not make a negative value positive in Objective-C, so neither does it here.
// MODIFICATION: Removed CAST_TO_INT macro, replaced with native ES6 Math.trunc().
return Math.trunc(self);
}
- (unsigned short)unsignedShortValue
{
// Despite the name this method does not make a negative value positive in Objective-C, so neither does it here.
// MODIFICATION: Removed CAST_TO_INT macro, replaced with native ES6 Math.trunc().
return Math.trunc(self);
}
- (CPComparisonResult)compare:(CPNumber)aNumber
{
if (aNumber == nil || aNumber['isa'] === CPNull)
[CPException raise:CPInvalidArgumentException reason:"nil argument"];
if (self > aNumber)
return CPOrderedDescending;
else if (self < aNumber)
return CPOrderedAscending;
return CPOrderedSame;
}
- (BOOL)isEqualToNumber:(CPNumber)aNumber
{
return self == aNumber;
}
@end
@implementation CPNumber (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
return [aCoder decodeObjectForKey:@"self"];
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeNumber:self forKey:@"self"];
}
@end
if (Number.prototype.isa !== CPNumber)
{
Object.defineProperties(Number.prototype,
{
isa:
{
value: CPNumber,
enumerable: false,
writable: true
}
});
}
if (Boolean.prototype.isa !== CPNumber)
{
Object.defineProperties(Boolean.prototype,
{
isa:
{
value: CPNumber,
enumerable: false,
writable: true
}
});
}
[CPNumber initialize];