2001-12-17 14:31:42 +00:00
|
|
|
|
/** NSValue.m - Object encapsulation for C types.
|
1999-06-14 09:31:43 +00:00
|
|
|
|
Copyright (C) 1993, 1994, 1996, 1999 Free Software Foundation, Inc.
|
1995-03-22 22:29:33 +00:00
|
|
|
|
|
|
|
|
|
Written by: Adam Fedor <fedor@boulder.colorado.edu>
|
|
|
|
|
Date: Mar 1995
|
2005-11-06 13:53:40 +00:00
|
|
|
|
Updated by: Richard Frith-Macdonald <rfm@gnu.org>
|
2001-01-12 16:48:33 +00:00
|
|
|
|
Date: Jan 2001
|
1995-03-22 22:29:33 +00:00
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
|
This file is part of the GNUstep Base Library.
|
1995-03-22 22:29:33 +00:00
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
1995-03-22 22:29:33 +00:00
|
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1995-03-22 22:29:33 +00:00
|
|
|
|
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
|
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
1995-03-22 22:29:33 +00:00
|
|
|
|
License along with this library; if not, write to the Free
|
2006-10-20 10:56:27 +00:00
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
|
Boston, MA 02111 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
|
|
|
|
|
<title>NSValue class reference</title>
|
|
|
|
|
$Date$ $Revision$
|
1995-03-22 22:29:33 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2010-02-19 08:12:46 +00:00
|
|
|
|
#import "common.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
|
#import "Foundation/NSValue.h"
|
|
|
|
|
#import "Foundation/NSCoder.h"
|
|
|
|
|
#import "Foundation/NSDictionary.h"
|
|
|
|
|
#import "Foundation/NSException.h"
|
|
|
|
|
#import "Foundation/NSMapTable.h"
|
|
|
|
|
#import "Foundation/NSLock.h"
|
|
|
|
|
#import "Foundation/NSData.h"
|
|
|
|
|
#import "GNUstepBase/NSObject+GNUstepBase.h"
|
2001-01-12 16:48:33 +00:00
|
|
|
|
|
|
|
|
|
@interface GSPlaceholderValue : NSValue
|
|
|
|
|
@end
|
1995-03-22 22:29:33 +00:00
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
@class GSValue;
|
2005-07-08 11:48:37 +00:00
|
|
|
|
@interface GSValue : NSObject // Help the compiler
|
|
|
|
|
@end
|
2001-01-12 14:29:34 +00:00
|
|
|
|
@class GSNonretainedObjectValue;
|
2005-07-08 11:48:37 +00:00
|
|
|
|
@interface GSNonretainedObjectValue : NSObject // Help the compiler
|
|
|
|
|
@end
|
2001-01-12 14:29:34 +00:00
|
|
|
|
@class GSPointValue;
|
2005-07-08 11:48:37 +00:00
|
|
|
|
@interface GSPointValue : NSObject // Help the compiler
|
|
|
|
|
@end
|
2001-01-12 14:29:34 +00:00
|
|
|
|
@class GSPointerValue;
|
2005-07-08 11:48:37 +00:00
|
|
|
|
@interface GSPointerValue : NSObject // Help the compiler
|
|
|
|
|
@end
|
2001-01-12 14:29:34 +00:00
|
|
|
|
@class GSRangeValue;
|
2005-07-08 11:48:37 +00:00
|
|
|
|
@interface GSRangeValue : NSObject // Help the compiler
|
|
|
|
|
@end
|
2001-01-12 14:29:34 +00:00
|
|
|
|
@class GSRectValue;
|
2005-07-08 11:48:37 +00:00
|
|
|
|
@interface GSRectValue : NSObject // Help the compiler
|
|
|
|
|
@end
|
2001-01-12 14:29:34 +00:00
|
|
|
|
@class GSSizeValue;
|
2005-07-08 11:48:37 +00:00
|
|
|
|
@interface GSSizeValue : NSObject // Help the compiler
|
|
|
|
|
@end
|
|
|
|
|
@class NSDataStatic; // Needed for decoding.
|
2011-07-24 13:09:22 +00:00
|
|
|
|
@interface NSDataStatic : NSData // Help the compiler
|
2005-07-08 11:48:37 +00:00
|
|
|
|
@end
|
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
static Class abstractClass;
|
|
|
|
|
static Class concreteClass;
|
|
|
|
|
static Class nonretainedObjectValueClass;
|
|
|
|
|
static Class pointValueClass;
|
|
|
|
|
static Class pointerValueClass;
|
2001-01-12 14:29:34 +00:00
|
|
|
|
static Class rangeValueClass;
|
1999-06-14 09:31:43 +00:00
|
|
|
|
static Class rectValueClass;
|
|
|
|
|
static Class sizeValueClass;
|
2001-01-12 16:48:33 +00:00
|
|
|
|
static Class GSPlaceholderValueClass;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static GSPlaceholderValue *defaultPlaceholderValue;
|
|
|
|
|
static NSMapTable *placeholderMap;
|
|
|
|
|
static NSLock *placeholderLock;
|
1995-08-30 21:49:35 +00:00
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
@implementation NSValue
|
1995-08-30 21:49:35 +00:00
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
+ (void) initialize
|
1995-08-30 21:49:35 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
if (self == [NSValue class])
|
|
|
|
|
{
|
|
|
|
|
abstractClass = self;
|
2010-03-16 13:03:36 +00:00
|
|
|
|
[abstractClass setVersion: 3]; // Version 3
|
2001-01-12 14:29:34 +00:00
|
|
|
|
concreteClass = [GSValue class];
|
|
|
|
|
nonretainedObjectValueClass = [GSNonretainedObjectValue class];
|
|
|
|
|
pointValueClass = [GSPointValue class];
|
|
|
|
|
pointerValueClass = [GSPointerValue class];
|
|
|
|
|
rangeValueClass = [GSRangeValue class];
|
|
|
|
|
rectValueClass = [GSRectValue class];
|
|
|
|
|
sizeValueClass = [GSSizeValue class];
|
2001-01-12 16:48:33 +00:00
|
|
|
|
GSPlaceholderValueClass = [GSPlaceholderValue class];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set up infrastructure for placeholder values.
|
|
|
|
|
*/
|
|
|
|
|
defaultPlaceholderValue = (GSPlaceholderValue*)
|
|
|
|
|
NSAllocateObject(GSPlaceholderValueClass, 0, NSDefaultMallocZone());
|
2011-06-19 13:34:17 +00:00
|
|
|
|
[[NSObject leakAt: (id*)&defaultPlaceholderValue] release];
|
2001-01-12 16:48:33 +00:00
|
|
|
|
placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
|
|
|
|
NSNonRetainedObjectMapValueCallBacks, 0);
|
2011-06-19 13:34:17 +00:00
|
|
|
|
[[NSObject leakAt: (id*)&placeholderMap] release];
|
2001-01-12 16:48:33 +00:00
|
|
|
|
placeholderLock = [NSLock new];
|
2011-06-19 13:34:17 +00:00
|
|
|
|
[[NSObject leakAt: (id*)&placeholderLock] release];
|
1999-06-14 09:31:43 +00:00
|
|
|
|
}
|
1995-08-30 21:49:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
1995-08-30 21:49:35 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
if (self == abstractClass)
|
2001-01-12 16:48:33 +00:00
|
|
|
|
{
|
|
|
|
|
if (z == NSDefaultMallocZone() || z == 0)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* As a special case, we can return a placeholder for a value
|
|
|
|
|
* in the default malloc zone extremely efficiently.
|
|
|
|
|
*/
|
|
|
|
|
return defaultPlaceholderValue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
id obj;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For anything other than the default zone, we need to
|
|
|
|
|
* locate the correct placeholder in the (lock protected)
|
|
|
|
|
* table of placeholders.
|
|
|
|
|
*/
|
|
|
|
|
[placeholderLock lock];
|
|
|
|
|
obj = (id)NSMapGet(placeholderMap, (void*)z);
|
|
|
|
|
if (obj == nil)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* There is no placeholder object for this zone, so we
|
|
|
|
|
* create a new one and use that.
|
|
|
|
|
*/
|
|
|
|
|
obj = (id)NSAllocateObject(GSPlaceholderValueClass, 0, z);
|
|
|
|
|
NSMapInsert(placeholderMap, (void*)z, (void*)obj);
|
|
|
|
|
}
|
|
|
|
|
[placeholderLock unlock];
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-06-14 09:31:43 +00:00
|
|
|
|
else
|
2001-01-12 16:48:33 +00:00
|
|
|
|
{
|
|
|
|
|
return NSAllocateObject(self, 0, z);
|
|
|
|
|
}
|
1995-08-30 21:49:35 +00:00
|
|
|
|
}
|
1995-03-22 22:29:33 +00:00
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
// NSCopying - always a simple retain.
|
1995-03-22 22:29:33 +00:00
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
- (id) copy
|
1998-03-12 14:21:20 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
return RETAIN(self);
|
1998-03-12 14:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
- (id) copyWithZone: (NSZone *)zone
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
return RETAIN(self);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-04-03 20:07:18 +00:00
|
|
|
|
/* Returns the concrete class associated with the type encoding */
|
1999-06-14 09:31:43 +00:00
|
|
|
|
+ (Class) valueClassWithObjCType: (const char *)type
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
Class theClass = concreteClass;
|
|
|
|
|
|
|
|
|
|
/* Let someone else deal with this error */
|
|
|
|
|
if (!type)
|
1995-04-03 20:07:18 +00:00
|
|
|
|
return theClass;
|
1999-06-14 09:31:43 +00:00
|
|
|
|
|
|
|
|
|
if (strcmp(@encode(id), type) == 0)
|
|
|
|
|
theClass = nonretainedObjectValueClass;
|
|
|
|
|
else if (strcmp(@encode(NSPoint), type) == 0)
|
|
|
|
|
theClass = pointValueClass;
|
|
|
|
|
else if (strcmp(@encode(void *), type) == 0)
|
|
|
|
|
theClass = pointerValueClass;
|
2001-01-12 14:29:34 +00:00
|
|
|
|
else if (strcmp(@encode(NSRange), type) == 0)
|
|
|
|
|
theClass = rangeValueClass;
|
1999-06-14 09:31:43 +00:00
|
|
|
|
else if (strcmp(@encode(NSRect), type) == 0)
|
|
|
|
|
theClass = rectValueClass;
|
|
|
|
|
else if (strcmp(@encode(NSSize), type) == 0)
|
|
|
|
|
theClass = sizeValueClass;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
return theClass;
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
|
// Allocating and Initializing
|
1995-04-03 20:07:18 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
+ (NSValue*) value: (const void *)value
|
1999-06-14 09:31:43 +00:00
|
|
|
|
withObjCType: (const char *)type
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
Class theClass = [self valueClassWithObjCType: type];
|
|
|
|
|
NSValue *theObj;
|
|
|
|
|
|
|
|
|
|
theObj = [theClass allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
theObj = [theObj initWithBytes: value objCType: type];
|
|
|
|
|
return AUTORELEASE(theObj);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
+ (NSValue*) valueWithBytes: (const void *)value
|
1999-06-14 09:31:43 +00:00
|
|
|
|
objCType: (const char *)type
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
Class theClass = [self valueClassWithObjCType: type];
|
|
|
|
|
NSValue *theObj;
|
|
|
|
|
|
|
|
|
|
theObj = [theClass allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
theObj = [theObj initWithBytes: value objCType: type];
|
|
|
|
|
return AUTORELEASE(theObj);
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
+ (NSValue*) valueWithNonretainedObject: (id)anObject
|
1999-06-14 09:31:43 +00:00
|
|
|
|
{
|
|
|
|
|
NSValue *theObj;
|
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
theObj = [nonretainedObjectValueClass allocWithZone: NSDefaultMallocZone()];
|
1999-06-14 09:31:43 +00:00
|
|
|
|
theObj = [theObj initWithBytes: &anObject objCType: @encode(id)];
|
|
|
|
|
return AUTORELEASE(theObj);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
+ (NSValue*) valueWithPoint: (NSPoint)point
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
NSValue *theObj;
|
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
theObj = [pointValueClass allocWithZone: NSDefaultMallocZone()];
|
1999-06-14 09:31:43 +00:00
|
|
|
|
theObj = [theObj initWithBytes: &point objCType: @encode(NSPoint)];
|
|
|
|
|
return AUTORELEASE(theObj);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
+ (NSValue*) valueWithPointer: (const void *)pointer
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
NSValue *theObj;
|
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
theObj = [pointerValueClass allocWithZone: NSDefaultMallocZone()];
|
1999-06-14 09:31:43 +00:00
|
|
|
|
theObj = [theObj initWithBytes: &pointer objCType: @encode(void*)];
|
|
|
|
|
return AUTORELEASE(theObj);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
+ (NSValue*) valueWithRange: (NSRange)range
|
|
|
|
|
{
|
|
|
|
|
NSValue *theObj;
|
|
|
|
|
|
|
|
|
|
theObj = [rangeValueClass allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
theObj = [theObj initWithBytes: &range objCType: @encode(NSRange)];
|
|
|
|
|
return AUTORELEASE(theObj);
|
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
+ (NSValue*) valueWithRect: (NSRect)rect
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
NSValue *theObj;
|
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
theObj = [rectValueClass allocWithZone: NSDefaultMallocZone()];
|
1999-06-14 09:31:43 +00:00
|
|
|
|
theObj = [theObj initWithBytes: &rect objCType: @encode(NSRect)];
|
|
|
|
|
return AUTORELEASE(theObj);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
+ (NSValue*) valueWithSize: (NSSize)size
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
NSValue *theObj;
|
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
theObj = [sizeValueClass allocWithZone: NSDefaultMallocZone()];
|
1999-06-14 09:31:43 +00:00
|
|
|
|
theObj = [theObj initWithBytes: &size objCType: @encode(NSSize)];
|
|
|
|
|
return AUTORELEASE(theObj);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
+ (NSValue*) valueFromString: (NSString *)string
|
1997-09-18 14:56:47 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
NSDictionary *dict = [string propertyList];
|
|
|
|
|
|
2001-01-12 16:48:33 +00:00
|
|
|
|
if (dict == nil)
|
1997-09-18 14:56:47 +00:00
|
|
|
|
return nil;
|
|
|
|
|
|
2001-01-12 16:48:33 +00:00
|
|
|
|
if ([dict objectForKey: @"location"])
|
|
|
|
|
{
|
|
|
|
|
NSRange range;
|
|
|
|
|
range = NSMakeRange([[dict objectForKey: @"location"] intValue],
|
|
|
|
|
[[dict objectForKey: @"length"] intValue]);
|
2010-12-23 02:23:05 +00:00
|
|
|
|
return [abstractClass valueWithRange: range];
|
2001-01-12 16:48:33 +00:00
|
|
|
|
}
|
|
|
|
|
else if ([dict objectForKey: @"width"] && [dict objectForKey: @"x"])
|
1997-09-18 14:56:47 +00:00
|
|
|
|
{
|
|
|
|
|
NSRect rect;
|
|
|
|
|
rect = NSMakeRect([[dict objectForKey: @"x"] floatValue],
|
|
|
|
|
[[dict objectForKey: @"y"] floatValue],
|
|
|
|
|
[[dict objectForKey: @"width"] floatValue],
|
|
|
|
|
[[dict objectForKey: @"height"] floatValue]);
|
1999-06-14 09:31:43 +00:00
|
|
|
|
return [abstractClass valueWithRect: rect];
|
1997-09-18 14:56:47 +00:00
|
|
|
|
}
|
|
|
|
|
else if ([dict objectForKey: @"width"])
|
|
|
|
|
{
|
|
|
|
|
NSSize size;
|
|
|
|
|
size = NSMakeSize([[dict objectForKey: @"width"] floatValue],
|
|
|
|
|
[[dict objectForKey: @"height"] floatValue]);
|
1999-06-14 09:31:43 +00:00
|
|
|
|
return [abstractClass valueWithSize: size];
|
1997-09-18 14:56:47 +00:00
|
|
|
|
}
|
|
|
|
|
else if ([dict objectForKey: @"x"])
|
|
|
|
|
{
|
|
|
|
|
NSPoint point;
|
|
|
|
|
point = NSMakePoint([[dict objectForKey: @"x"] floatValue],
|
|
|
|
|
[[dict objectForKey: @"y"] floatValue]);
|
1999-06-14 09:31:43 +00:00
|
|
|
|
return [abstractClass valueWithPoint: point];
|
1997-09-18 14:56:47 +00:00
|
|
|
|
}
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
- (id) initWithBytes: (const void*)data objCType: (const char*)type
|
|
|
|
|
{
|
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1997-09-18 14:56:47 +00:00
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
|
// Accessing Data
|
1995-04-03 20:07:18 +00:00
|
|
|
|
/* All the rest of these methods must be implemented by a subclass */
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (void) getValue: (void *)value
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (BOOL) isEqual: (id)other
|
1998-03-12 14:21:20 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
if ([other isKindOfClass: [self class]])
|
|
|
|
|
{
|
2000-08-07 22:00:31 +00:00
|
|
|
|
return [self isEqualToValue: other];
|
1998-03-12 14:21:20 +00:00
|
|
|
|
}
|
1999-06-14 09:31:43 +00:00
|
|
|
|
return NO;
|
1998-03-12 14:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (BOOL) isEqualToValue: (NSValue*)other
|
1998-03-12 14:21:20 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return NO;
|
1998-03-12 14:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (const char *) objCType
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return 0;
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (id) nonretainedObjectValue
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return 0;
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (void *) pointerValue
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return 0;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
}
|
1995-03-22 22:29:33 +00:00
|
|
|
|
|
2001-01-12 14:29:34 +00:00
|
|
|
|
- (NSRange) rangeValue
|
|
|
|
|
{
|
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return NSMakeRange(0,0);
|
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (NSRect) rectValue
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return NSMakeRect(0,0,0,0);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (NSSize) sizeValue
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return NSMakeSize(0,0);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
|
- (NSPoint) pointValue
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
1999-06-14 09:31:43 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return NSMakePoint(0,0);
|
1995-04-03 20:07:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-01-12 16:48:33 +00:00
|
|
|
|
- (Class) classForCoder
|
|
|
|
|
{
|
|
|
|
|
return abstractClass;
|
|
|
|
|
}
|
1995-03-22 22:29:33 +00:00
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
- (void) encodeWithCoder: (NSCoder *)coder
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
2011-05-12 16:03:08 +00:00
|
|
|
|
NSUInteger tsize;
|
2001-01-12 16:48:33 +00:00
|
|
|
|
unsigned size;
|
2002-02-21 13:04:34 +00:00
|
|
|
|
const char *data;
|
2001-01-12 16:48:33 +00:00
|
|
|
|
const char *objctype = [self objCType];
|
2001-12-03 12:44:33 +00:00
|
|
|
|
NSMutableData *d;
|
2001-01-12 16:48:33 +00:00
|
|
|
|
|
|
|
|
|
size = strlen(objctype)+1;
|
|
|
|
|
[coder encodeValueOfObjCType: @encode(unsigned) at: &size];
|
2001-05-11 15:23:24 +00:00
|
|
|
|
[coder encodeArrayOfObjCType: @encode(signed char) count: size at: objctype];
|
2010-03-16 13:03:36 +00:00
|
|
|
|
if (strncmp("{_NSSize=", objctype, 9) == 0)
|
|
|
|
|
{
|
|
|
|
|
NSSize v = [self sizeValue];
|
|
|
|
|
|
|
|
|
|
[coder encodeValueOfObjCType: objctype at: &v];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (strncmp("{_NSPoint=", objctype, 10) == 0)
|
|
|
|
|
{
|
|
|
|
|
NSPoint v = [self pointValue];
|
|
|
|
|
|
|
|
|
|
[coder encodeValueOfObjCType: objctype at: &v];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (strncmp("{_NSRect=", objctype, 9) == 0)
|
|
|
|
|
{
|
|
|
|
|
NSRect v = [self rectValue];
|
|
|
|
|
|
|
|
|
|
[coder encodeValueOfObjCType: objctype at: &v];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (strncmp("{_NSRange=", objctype, 10) == 0)
|
|
|
|
|
{
|
|
|
|
|
NSRange v = [self rangeValue];
|
|
|
|
|
|
|
|
|
|
[coder encodeValueOfObjCType: objctype at: &v];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-12 16:03:08 +00:00
|
|
|
|
NSGetSizeAndAlignment(objctype, 0, &tsize);
|
|
|
|
|
data = (void *)NSZoneMalloc([self zone], tsize);
|
2001-01-12 16:48:33 +00:00
|
|
|
|
[self getValue: (void*)data];
|
2001-12-03 12:44:33 +00:00
|
|
|
|
d = [NSMutableData new];
|
|
|
|
|
[d serializeDataAt: data ofObjCType: objctype context: nil];
|
2002-02-21 13:04:34 +00:00
|
|
|
|
size = [d length];
|
|
|
|
|
[coder encodeValueOfObjCType: @encode(unsigned) at: &size];
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), (void*)data);
|
|
|
|
|
data = [d bytes];
|
|
|
|
|
[coder encodeArrayOfObjCType: @encode(unsigned char) count: size at: data];
|
2001-12-03 12:44:33 +00:00
|
|
|
|
RELEASE(d);
|
1995-03-22 22:29:33 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1999-06-14 09:31:43 +00:00
|
|
|
|
- (id) initWithCoder: (NSCoder *)coder
|
1995-03-22 22:29:33 +00:00
|
|
|
|
{
|
2001-12-04 08:44:42 +00:00
|
|
|
|
char type[64];
|
2001-01-12 16:48:33 +00:00
|
|
|
|
const char *objctype;
|
|
|
|
|
Class c;
|
|
|
|
|
id o;
|
2011-05-12 16:03:08 +00:00
|
|
|
|
NSUInteger tsize;
|
2001-01-12 16:48:33 +00:00
|
|
|
|
unsigned size;
|
2001-12-04 08:44:42 +00:00
|
|
|
|
int ver;
|
2001-01-12 16:48:33 +00:00
|
|
|
|
|
|
|
|
|
[coder decodeValueOfObjCType: @encode(unsigned) at: &size];
|
2001-12-04 08:44:42 +00:00
|
|
|
|
/*
|
|
|
|
|
* For almost all type encodings, we can use space on the stack,
|
|
|
|
|
* but to handle exceptionally large ones (possibly some huge structs)
|
|
|
|
|
* we have a strategy of allocating and deallocating heap space too.
|
|
|
|
|
*/
|
|
|
|
|
if (size <= 64)
|
|
|
|
|
{
|
|
|
|
|
objctype = type;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
objctype = (void*)NSZoneMalloc(NSDefaultMallocZone(), size);
|
|
|
|
|
}
|
2001-12-03 08:07:21 +00:00
|
|
|
|
[coder decodeArrayOfObjCType: @encode(signed char)
|
|
|
|
|
count: size
|
|
|
|
|
at: (void*)objctype];
|
2010-03-16 13:03:36 +00:00
|
|
|
|
if (strncmp("{_NSSize=", objctype, 9) == 0)
|
|
|
|
|
c = [abstractClass valueClassWithObjCType: @encode(NSSize)];
|
|
|
|
|
else if (strncmp("{_NSPoint=", objctype, 10) == 0)
|
|
|
|
|
c = [abstractClass valueClassWithObjCType: @encode(NSPoint)];
|
|
|
|
|
else if (strncmp("{_NSRect=", objctype, 9) == 0)
|
|
|
|
|
c = [abstractClass valueClassWithObjCType: @encode(NSRect)];
|
|
|
|
|
else if (strncmp("{_NSRange=", objctype, 10) == 0)
|
|
|
|
|
c = [abstractClass valueClassWithObjCType: @encode(NSRange)];
|
|
|
|
|
else
|
|
|
|
|
c = [abstractClass valueClassWithObjCType: objctype];
|
2001-12-04 08:44:42 +00:00
|
|
|
|
o = [c allocWithZone: [coder objectZone]];
|
2001-12-03 12:44:33 +00:00
|
|
|
|
|
2001-12-04 08:44:42 +00:00
|
|
|
|
ver = [coder versionForClassName: @"NSValue"];
|
2010-03-16 13:03:36 +00:00
|
|
|
|
if (ver > 2)
|
|
|
|
|
{
|
|
|
|
|
if (c == pointValueClass)
|
|
|
|
|
{
|
|
|
|
|
NSPoint v;
|
|
|
|
|
|
|
|
|
|
[coder decodeValueOfObjCType: @encode(NSPoint) at: &v];
|
|
|
|
|
DESTROY(self);
|
|
|
|
|
return [o initWithBytes: &v objCType: @encode(NSPoint)];
|
|
|
|
|
}
|
|
|
|
|
else if (c == sizeValueClass)
|
|
|
|
|
{
|
|
|
|
|
NSSize v;
|
|
|
|
|
|
|
|
|
|
[coder decodeValueOfObjCType: @encode(NSSize) at: &v];
|
|
|
|
|
DESTROY(self);
|
|
|
|
|
return [o initWithBytes: &v objCType: @encode(NSSize)];
|
|
|
|
|
}
|
|
|
|
|
else if (c == rangeValueClass)
|
|
|
|
|
{
|
|
|
|
|
NSRange v;
|
|
|
|
|
|
|
|
|
|
[coder decodeValueOfObjCType: @encode(NSRange) at: &v];
|
|
|
|
|
DESTROY(self);
|
|
|
|
|
return [o initWithBytes: &v objCType: @encode(NSRange)];
|
|
|
|
|
}
|
|
|
|
|
else if (c == rectValueClass)
|
|
|
|
|
{
|
|
|
|
|
NSRect v;
|
|
|
|
|
|
|
|
|
|
[coder decodeValueOfObjCType: @encode(NSRect) at: &v];
|
|
|
|
|
DESTROY(self);
|
|
|
|
|
return [o initWithBytes: &v objCType: @encode(NSRect)];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-02-21 13:17:39 +00:00
|
|
|
|
if (ver < 2)
|
2001-12-04 08:44:42 +00:00
|
|
|
|
{
|
2002-02-21 13:17:39 +00:00
|
|
|
|
if (ver < 1)
|
2001-12-04 08:44:42 +00:00
|
|
|
|
{
|
2002-02-21 13:17:39 +00:00
|
|
|
|
if (c == pointValueClass)
|
|
|
|
|
{
|
|
|
|
|
NSPoint v;
|
2001-12-04 08:44:42 +00:00
|
|
|
|
|
2002-02-21 13:17:39 +00:00
|
|
|
|
[coder decodeValueOfObjCType: @encode(NSPoint) at: &v];
|
|
|
|
|
o = [o initWithBytes: &v objCType: @encode(NSPoint)];
|
|
|
|
|
}
|
|
|
|
|
else if (c == sizeValueClass)
|
|
|
|
|
{
|
|
|
|
|
NSSize v;
|
2001-12-04 08:44:42 +00:00
|
|
|
|
|
2002-02-21 13:17:39 +00:00
|
|
|
|
[coder decodeValueOfObjCType: @encode(NSSize) at: &v];
|
|
|
|
|
o = [o initWithBytes: &v objCType: @encode(NSSize)];
|
|
|
|
|
}
|
|
|
|
|
else if (c == rangeValueClass)
|
|
|
|
|
{
|
|
|
|
|
NSRange v;
|
2001-12-04 08:44:42 +00:00
|
|
|
|
|
2002-02-21 13:17:39 +00:00
|
|
|
|
[coder decodeValueOfObjCType: @encode(NSRange) at: &v];
|
|
|
|
|
o = [o initWithBytes: &v objCType: @encode(NSRange)];
|
|
|
|
|
}
|
|
|
|
|
else if (c == rectValueClass)
|
|
|
|
|
{
|
|
|
|
|
NSRect v;
|
2001-12-04 08:44:42 +00:00
|
|
|
|
|
2002-02-21 13:17:39 +00:00
|
|
|
|
[coder decodeValueOfObjCType: @encode(NSRect) at: &v];
|
|
|
|
|
o = [o initWithBytes: &v objCType: @encode(NSRect)];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unsigned char *data;
|
|
|
|
|
|
|
|
|
|
[coder decodeValueOfObjCType: @encode(unsigned) at: &size];
|
|
|
|
|
data = (void *)NSZoneMalloc(NSDefaultMallocZone(), size);
|
|
|
|
|
[coder decodeArrayOfObjCType: @encode(unsigned char)
|
|
|
|
|
count: size
|
|
|
|
|
at: (void*)data];
|
|
|
|
|
o = [o initWithBytes: data objCType: objctype];
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), data);
|
|
|
|
|
}
|
2001-12-04 08:44:42 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-02-23 20:42:32 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
unsigned cursor = 0;
|
2001-12-04 08:44:42 +00:00
|
|
|
|
|
2002-02-21 13:17:39 +00:00
|
|
|
|
/*
|
|
|
|
|
* For performance, decode small values directly onto the stack,
|
|
|
|
|
* For larger values we allocate and deallocate heap space.
|
|
|
|
|
*/
|
2011-05-12 16:03:08 +00:00
|
|
|
|
NSGetSizeAndAlignment(objctype, 0, &tsize);
|
|
|
|
|
if (tsize <= 64)
|
2002-02-21 13:17:39 +00:00
|
|
|
|
{
|
2011-05-12 16:03:08 +00:00
|
|
|
|
unsigned char data[tsize];
|
2002-02-21 13:17:39 +00:00
|
|
|
|
|
|
|
|
|
[coder decodeValueOfObjCType: @encode(id) at: &d];
|
|
|
|
|
[d deserializeDataAt: data
|
|
|
|
|
ofObjCType: objctype
|
|
|
|
|
atCursor: &cursor
|
|
|
|
|
context: nil];
|
|
|
|
|
o = [o initWithBytes: data objCType: objctype];
|
|
|
|
|
RELEASE(d);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unsigned char *data;
|
|
|
|
|
|
2011-05-12 16:03:08 +00:00
|
|
|
|
data = (void *)NSZoneMalloc(NSDefaultMallocZone(), tsize);
|
2002-02-21 13:17:39 +00:00
|
|
|
|
[coder decodeValueOfObjCType: @encode(id) at: &d];
|
|
|
|
|
[d deserializeDataAt: data
|
|
|
|
|
ofObjCType: objctype
|
|
|
|
|
atCursor: &cursor
|
|
|
|
|
context: nil];
|
|
|
|
|
o = [o initWithBytes: data objCType: objctype];
|
|
|
|
|
RELEASE(d);
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), data);
|
|
|
|
|
}
|
2001-12-04 08:44:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-02-21 13:04:34 +00:00
|
|
|
|
static NSData *d = nil;
|
2009-02-23 20:42:32 +00:00
|
|
|
|
unsigned cursor = 0;
|
2001-12-04 08:44:42 +00:00
|
|
|
|
|
2002-02-21 13:04:34 +00:00
|
|
|
|
if (d == nil)
|
|
|
|
|
{
|
|
|
|
|
d = [NSDataStatic allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
}
|
2001-12-04 08:44:42 +00:00
|
|
|
|
/*
|
|
|
|
|
* For performance, decode small values directly onto the stack,
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* For larger values we allocate and deallocate heap space.
|
2001-12-04 08:44:42 +00:00
|
|
|
|
*/
|
2011-05-12 16:03:08 +00:00
|
|
|
|
NSGetSizeAndAlignment(objctype, 0, &tsize);
|
|
|
|
|
if (tsize <= 64)
|
2001-12-04 08:44:42 +00:00
|
|
|
|
{
|
2011-05-12 16:03:08 +00:00
|
|
|
|
unsigned char data[tsize];
|
2001-12-04 08:44:42 +00:00
|
|
|
|
|
2002-02-21 13:04:34 +00:00
|
|
|
|
[coder decodeValueOfObjCType: @encode(unsigned) at: &size];
|
|
|
|
|
{
|
|
|
|
|
unsigned char serialized[size];
|
|
|
|
|
|
|
|
|
|
[coder decodeArrayOfObjCType: @encode(unsigned char)
|
|
|
|
|
count: size
|
|
|
|
|
at: (void*)serialized];
|
|
|
|
|
d = [d initWithBytesNoCopy: (void*)serialized length: size];
|
|
|
|
|
[d deserializeDataAt: data
|
|
|
|
|
ofObjCType: objctype
|
|
|
|
|
atCursor: &cursor
|
|
|
|
|
context: nil];
|
|
|
|
|
}
|
2001-12-04 08:44:42 +00:00
|
|
|
|
o = [o initWithBytes: data objCType: objctype];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-02-21 13:04:34 +00:00
|
|
|
|
void *data;
|
2001-12-04 08:44:42 +00:00
|
|
|
|
|
2011-05-12 16:03:08 +00:00
|
|
|
|
data = (void *)NSZoneMalloc(NSDefaultMallocZone(), tsize);
|
2002-02-21 13:04:34 +00:00
|
|
|
|
[coder decodeValueOfObjCType: @encode(unsigned) at: &size];
|
|
|
|
|
{
|
|
|
|
|
void *serialized;
|
|
|
|
|
|
|
|
|
|
serialized = (void *)NSZoneMalloc(NSDefaultMallocZone(), size);
|
|
|
|
|
[coder decodeArrayOfObjCType: @encode(unsigned char)
|
|
|
|
|
count: size
|
|
|
|
|
at: serialized];
|
|
|
|
|
d = [d initWithBytesNoCopy: serialized length: size];
|
|
|
|
|
[d deserializeDataAt: data
|
|
|
|
|
ofObjCType: objctype
|
|
|
|
|
atCursor: &cursor
|
|
|
|
|
context: nil];
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), serialized);
|
|
|
|
|
}
|
2001-12-04 08:44:42 +00:00
|
|
|
|
o = [o initWithBytes: data objCType: objctype];
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (objctype != type)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), (void*)objctype);
|
|
|
|
|
}
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2001-01-12 16:48:33 +00:00
|
|
|
|
self = o;
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation GSPlaceholderValue
|
|
|
|
|
|
|
|
|
|
- (id) autorelease
|
|
|
|
|
{
|
|
|
|
|
NSWarnLog(@"-autorelease sent to uninitialised value");
|
|
|
|
|
return self; // placeholders never get released.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2006-06-04 06:42:10 +00:00
|
|
|
|
GSNOSUPERDEALLOC; // placeholders never get deallocated.
|
2001-01-12 16:48:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-10-12 13:34:01 +00:00
|
|
|
|
- (void) getValue: (void*)data
|
2001-01-12 16:48:33 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"attempt to use uninitialised value"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithBytes: (const void*)data objCType: (const char*)type
|
|
|
|
|
{
|
|
|
|
|
Class c = [abstractClass valueClassWithObjCType: type];
|
|
|
|
|
|
2010-03-05 09:30:18 +00:00
|
|
|
|
self = (id)NSAllocateObject(c, 0, [self zone]);
|
2001-01-12 16:48:33 +00:00
|
|
|
|
return [self initWithBytes: data objCType: type];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (const char*) objCType
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"attempt to use uninitialised value"];
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-31 15:31:39 +00:00
|
|
|
|
- (oneway void) release
|
2001-01-12 16:48:33 +00:00
|
|
|
|
{
|
|
|
|
|
return; // placeholders never get released.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) retain
|
|
|
|
|
{
|
|
|
|
|
return self; // placeholders never get retained.
|
|
|
|
|
}
|
1995-03-22 22:29:33 +00:00
|
|
|
|
@end
|
|
|
|
|
|