Apr 3 patch from Adam Fedor. See ChangeLog for details.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@249 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
mccallum 1995-04-03 20:07:18 +00:00
parent f81aa9757d
commit aea49bd3e2
8 changed files with 226 additions and 192 deletions

View file

@ -68,7 +68,7 @@
@end @end
@interface NSObject <NSObject, NSCoding> @interface NSObject <NSObject, NSCoding, NSCopying>
{ {
Class isa; Class isa;
} }

View file

@ -37,10 +37,6 @@
+ (NSValue*) valueWithRect: (NSRect)rect; + (NSValue*) valueWithRect: (NSRect)rect;
+ (NSValue*) valueWithSize: (NSSize)size; + (NSValue*) valueWithSize: (NSSize)size;
/* Note: not in OpenStep specification */
- initValue: (const void*)value
withObjCType: (const char*)type;
// Accessing Data // Accessing Data
- (void) getValue: (void*)value; - (void) getValue: (void*)value;
@ -53,7 +49,7 @@
@end @end
@interface NSNumber : NSValue @interface NSNumber : NSValue <NSCoding>
{ {
} }
@ -94,4 +90,15 @@
@end @end
/* Note: These methods are not in the OpenStep spec, but they may make
subclassing easier. */
@interface NSValue (Subclassing)
/* Used by value:withObjCType: to determine the concrete subclass to alloc */
+ (Class)valueClassWithObjCType:(const char *)type;
/* Designated initializer for all concrete subclasses */
- initValue:(const void *)value withObjCType:(const char *)type;
@end
#endif /* __NSValue_h_OBJECTS_INCLUDE */ #endif /* __NSValue_h_OBJECTS_INCLUDE */

View file

@ -164,12 +164,29 @@ NSObject.m \
NSString.m NSString.m
FEDOR_GNUSTEP_MFILES = \ FEDOR_GNUSTEP_MFILES = \
NSBundle.m \
NSException.m \ NSException.m \
NSGeometry.m \ NSGeometry.m \
NSNumber.m \ NSNumber.m \
NSRange.m \ NSRange.m \
NSValue.m NSValue.m \
NSConcreteValue.m
#NSArray.m \
#NSCoder.m \
#NSDictionary.m \
#NSBundle.m \
#FEDOR_GNUSTEP_CFILES = \
#objc-load.c \
#find_exec.c
FEDOR_CLUSTER_OBJS = $(NSVALUE_OFILES) $(NSNUMBER_OFILES)
NSVALUE_CLUSTER = 0 1 2 3 4
NSVALUE_OFILES = NSValue0.o NSValue1.o NSValue2.o NSValue3.o NSValue4.o
NSNUMBER_CLUSTER = 0 1 2 3 4 5 6 7 8 9 10 11 12
NSNUMBER_OFILES = NSNumber0.o NSNumber1.o NSNumber2.o NSNumber3.o \
NSNumber4.o NSNumber5.o NSNumber6.o NSNumber7.o NSNumber8.o \
NSNumber9.o NSNumber10.o NSNumber11.o NSNumber12.o
GNU_CFILES = \ GNU_CFILES = \
behavior.c \ behavior.c \
@ -193,6 +210,7 @@ GNUSTEP_OTHER_SRCFILES =
GNU_OBJS = $(GNU_MFILES:.m=.o) $(GNU_CFILES:.c=.o) GNU_OBJS = $(GNU_MFILES:.m=.o) $(GNU_CFILES:.c=.o)
NEXTSTEP_OBJS = $(NEXTSTEP_MFILES:.m=.o) $(NEXTSTEP_CFILES:.c=.o) NEXTSTEP_OBJS = $(NEXTSTEP_MFILES:.m=.o) $(NEXTSTEP_CFILES:.c=.o)
GNUSTEP_OBJS = $(GNUSTEP_MFILES:.m=.o) $(GNUSTEP_CFILES:.c=.o) GNUSTEP_OBJS = $(GNUSTEP_MFILES:.m=.o) $(GNUSTEP_CFILES:.c=.o)
FEDOR_GNUSTEP_OBJS = $(FEDOR_GNUSTEP_MFILES:.m=.o) $(FEDOR_GNUSTEP_CFILES:.c=.o) $(FEDOR_CLUSTER_OBJS)
GNU_HEADERS = \ GNU_HEADERS = \
objects/Array.h \ objects/Array.h \
@ -295,7 +313,9 @@ FEDOR_GNUSTEP_HEADERS = \
foundation/NSBundle.h \ foundation/NSBundle.h \
foundation/NSException.h \ foundation/NSException.h \
foundation/NSGeometry.h \ foundation/NSGeometry.h \
foundation/NSValue.h foundation/NSValue.h \
foundation/NSConcreteValue.h \
foundation/NSConcreteNumber.h
INSTALL_HEADERS = @INSTALL_HEADERS@ INSTALL_HEADERS = @INSTALL_HEADERS@
INSTALL_OBJS = @INSTALL_OBJS@ INSTALL_OBJS = @INSTALL_OBJS@
@ -353,6 +373,40 @@ depend:
rm -f $(srcdir)/Makefile.depend rm -f $(srcdir)/Makefile.depend
$(CC) $(ALL_INCLUDE_FLAGS) -M $(SRCS) > $(srcdir)/Makefile.depend $(CC) $(ALL_INCLUDE_FLAGS) -M $(SRCS) > $(srcdir)/Makefile.depend
# Compilation of class clusters
$(NSVALUE_OFILES) : NSCTemplateValue.m
for i in ${NSVALUE_CLUSTER}; do \
cp NSCTemplateValue.m NSCTemplateValue$$i.m; \
$(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_OBJCFLAGS) \
-DTYPE_ORDER=$$i NSCTemplateValue$$i.m -o NSValue$$i.o; \
rm -f NSCTemplateValue$$i.m; \
done
$(NSNUMBER_OFILES) : NSConcreteNumber.m
for i in ${NSNUMBER_CLUSTER}; do \
cp NSConcreteNumber.m NSConcreteNumber$$i.m; \
$(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_OBJCFLAGS) \
-DTYPE_ORDER=$$i -c NSConcreteNumber$$i.m -o NSNumber$$i.o; \
rm -f NSConcreteNumber$$i.m; \
done
# Compilation of class clusters
$(NSVALUE_OFILES) : NSCTemplateValue.m
for i in ${NSVALUE_CLUSTER}; do \
cp NSCTemplateValue.m NSCTemplateValue$$i.m; \
$(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_OBJCFLAGS) \
-DTYPE_ORDER=$$i NSCTemplateValue$$i.m -o NSValue$$i.o; \
rm -f NSCTemplateValue$$i.m; \
done
$(NSNUMBER_OFILES) : NSConcreteNumber.m
for i in ${NSNUMBER_CLUSTER}; do \
cp NSConcreteNumber.m NSConcreteNumber$$i.m; \
$(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_OBJCFLAGS) \
-DTYPE_ORDER=$$i -c NSConcreteNumber$$i.m -o NSNumber$$i.o; \
rm -f NSConcreteNumber$$i.m; \
done
NXStringTable_scan.c: NXStringTable_scan.l NXStringTable_scan.c: NXStringTable_scan.l
$(LEX) $(LFLAGS) -t NXStringTable_scan.l > NXStringTable_scan.temp $(LEX) $(LFLAGS) -t NXStringTable_scan.l > NXStringTable_scan.temp
sed 's/yy/NXlex_/g' < NXStringTable_scan.temp > NXStringTable_scan.c sed 's/yy/NXlex_/g' < NXStringTable_scan.temp > NXStringTable_scan.c
@ -459,6 +513,7 @@ clean: mostlyclean
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache rm -f Makefile config.status config.log config.cache
rm -f dynamic-load.h
realclean: distclean realclean: distclean
rm -f TAGS configure \ rm -f TAGS configure \

View file

@ -1,32 +1,54 @@
/* Implementation of NSBundle class /* Implementation of NSBundle class
* Copyright (C) 1993,1994,1995 Free Software Foundation, Inc.
* Copyright (C) 1993 The Board of Trustees of
* The Leland Stanford Junior University. All Rights Reserved. Written by: Adam Fedor <fedor@boulder.colorado.edu>
* Date: May 1993
* Authors: Adam Fedor, Scott Francis, Fred Harris, Paul Kunz, Tom Pavel,
* Imran Qureshi, and Libing Wang This file is part of the GNU Objective C Class Library.
*
* This file is part of an Objective-C class library This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* NSBundle.m,v 1.8 1993/10/20 00:44:53 pfkeb Exp License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <stdio.h>
#include <assert.h> #include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <sys/param.h> #include <sys/param.h> /* Needed by sys/stat */
#include <sys/stat.h> #include <sys/stat.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include <objects/objc-load.h> #include <objects/stdobjects.h>
#include <foundation/objc-load.h>
#include <foundation/NSBundle.h> #include <foundation/NSBundle.h>
#include <foundation/NSException.h> #include <foundation/NSException.h>
#include <foundation/NSString.h> #include <foundation/NSString.h>
#include <foundation/NSArray.h> #include <foundation/NSArray.h>
#ifndef index /* Deal with strchr: */
#define index strchr #if STDC_HEADERS || HAVE_STRING_H
#include <string.h>
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
#if !STDC_HEADERS && HAVE_MEMORY_H
#include <memory.h>
#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
#define rindex strrchr #define rindex strrchr
#endif #define bcopy(s, d, n) memcpy ((d), (s), (n))
#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
#define bzero(s, n) memset ((s), 0, (n))
#else /* not STDC_HEADERS and not HAVE_STRING_H */
#include <strings.h>
/* memory.h and strings.h conflict on some systems. */
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
#ifndef FREE_OBJECT #ifndef FREE_OBJECT
#define FFREE_OBJECT(id) ([id release],id=nil) #define FFREE_OBJECT(id) ([id release],id=nil)
@ -37,9 +59,10 @@
#define BUNDLE_EXT "bundle" #define BUNDLE_EXT "bundle"
/* By default, we transmorgrify extensions of type "nib" to type "xmib" /* By default, we transmorgrify extensions of type "nib" to type "xmib"
which is the common extension for IB files for the GnuStep project which is the common extension for IB files for the GNUStep project
*/ */
#define IB_EXT "xmib" static NSString *bundle_nib_ext = @"nib";
static NSString *bundle_xmib_ext = @"xmib";
/* Class variables - We keep track of all the bundles and all the classes /* Class variables - We keep track of all the bundles and all the classes
that are in each bundle that are in each bundle
@ -52,10 +75,10 @@ static NSMutableArray *_bundleClasses = nil;
static NSArray *_languages = nil; static NSArray *_languages = nil;
/* When we are linking in an object file, objc_load_modules calls our /* When we are linking in an object file, objc_load_modules calls our
callBack routine for every Class and Category loaded. The following callback routine for every Class and Category loaded. The following
variable stores the bundle that is currently doing the loading so we know variable stores the bundle that is currently doing the loading so we know
where to store the class names. This is way non-thread-safe, but where to store the class names.
apparently this is how NeXT does it (maybe?). FIXME: This should be put into a NSThread dictionary
*/ */
static int _loadingBundlePos = -1; static int _loadingBundlePos = -1;
@ -63,7 +86,7 @@ static BOOL _stripAfterLoading;
/* Get the object file that should be located in the bundle of the same name */ /* Get the object file that should be located in the bundle of the same name */
static NSString * static NSString *
object_name(NSString *path) bundle_object_name(NSString *path)
{ {
NSString *name; NSString *name;
name = [[path lastPathComponent] stringByDeletingPathExtension]; name = [[path lastPathComponent] stringByDeletingPathExtension];
@ -74,37 +97,30 @@ object_name(NSString *path)
/* Construct a path from the directory, language, name and extension. Used by /* Construct a path from the directory, language, name and extension. Used by
pathForResource:... pathForResource:...
*/ */
static NSString *nib;
static NSString *xmib;
static NSString * static NSString *
construct_path(NSString *path, NSString *lang, bundle_resource_path(NSString *path, NSString *lang, NSString *name,
NSString *name, NSString *ext ) NSString *ext )
{ {
NSString *fullpath; NSString *fullpath;
NSString *name_ext;
name_ext = [name pathExtension];
name = [name stringByDeletingPathExtension]; name = [name stringByDeletingPathExtension];
if ([ext compare:nib] == NSOrderedSame) // FIXME: we could check to see if name_ext and ext match, but what
ext = xmib; // would we do if they didn't?
// FIXME: change when NSString can support %@ parameters if (!ext)
ext = name_ext;
if ([ext compare:bundle_nib_ext] == NSOrderedSame)
ext = bundle_xmib_ext;
if (lang) { if (lang) {
fullpath = [NSString stringWithFormat: fullpath = [NSString stringWithFormat:
TEMP_STRING("%s/%s.lproj/%s.%s"), [path cString], @"%@/%@.lproj/%@", path, lang, name];
[lang cString], [name cString], [ext cString]];
} else { } else {
fullpath = [NSString stringWithFormat: fullpath = [NSString stringWithFormat: @"%@/%@", path, name];
TEMP_STRING("%s/%s.%s"), [path cString],
[name cString], [ext cString]];
} }
/* if (ext && [ext length] != 0)
if (lang) { fullpath = [NSString stringByAppendingPathExtension:ext];
fullpath = [NSString stringWithFormat:
TEMP_STRING("%@/%@.lproj/%@.%@"), path, lang, name, ext];
} else {
fullpath = [NSString stringWithFormat:
TEMP_STRING("%@/%@.%@"), path, name, ext];
}
*/
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Debug (NSBundle): path is %s\n", [fullpath cString]); fprintf(stderr, "Debug (NSBundle): path is %s\n", [fullpath cString]);
#endif #endif
@ -124,24 +140,17 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
@implementation NSBundle @implementation NSBundle
+ (void)initialize
{
nib = STATIC_STRING("nib");
xmib = STATIC_STRING("xmib");
}
+ (NSBundle *)mainBundle + (NSBundle *)mainBundle
{ {
if ( !_mainBundle ) { if ( !_mainBundle ) {
NSString *path; NSString *path;
path = [NSString stringWithCString:objc_executable_location()]; path = [NSString stringWithCString:objc_executable_location()];
assert(path);
assert([path length]);
/* Strip off the name of the program */ /* Strip off the name of the program */
path = [path stringByDeletingLastPathComponent]; path = [path stringByDeletingLastPathComponent];
if (!path || [path length] == 0) {
fprintf(stderr, "Error (NSBundle): Cannot find main bundle.\n");
return nil;
}
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Debug (NSBundle): Found main in %s\n", fprintf(stderr, "Debug (NSBundle): Found main in %s\n",
@ -165,6 +174,7 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
int i, count; int i, count;
NSBundle *bundle = nil; NSBundle *bundle = nil;
// FIXME: should this be an error if aClass == nil?
if (!aClass) if (!aClass)
return nil; return nil;
@ -205,13 +215,13 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
if (!path || [path length] == 0) { if (!path || [path length] == 0) {
[NSException raise:NSInvalidArgumentException [NSException raise:NSInvalidArgumentException
format:TEMP_STRING("No path specified for bundle")]; format:@"No path specified for bundle"];
/* NOT REACHED */ /* NOT REACHED */
} }
if (stat([path cString], &statbuf) != 0) { if (stat([path cString], &statbuf) != 0) {
[NSException raise:NSGenericException [NSException raise:NSGenericException
format:TEMP_STRING("Path does not exist")]; format:@"Could not find path %s", [path cString]];
/* NOT REACHED */ /* NOT REACHED */
} }
_path = [path retain]; _path = [path retain];
@ -254,11 +264,11 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
{ {
int j, class_count; int j, class_count;
NSArray *classList; NSArray *classList;
Class *theClass = Nil; Class theClass = Nil;
if (!_codeLoaded) { if (!_codeLoaded) {
if (self != _mainBundle && ![self principalClass]) { if (self != _mainBundle && ![self principalClass]) {
[NSException raise:NSGenericException [NSException raise:NSGenericException
format:TEMP_STRING("Unable to get classes")]; format:@"No classes in bundle"];
/* NOT REACHED */ /* NOT REACHED */
} }
} }
@ -292,13 +302,13 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
} }
if (!_codeLoaded) { if (!_codeLoaded) {
NSString *object = object_name(_path); NSString *object = bundle_object_name(_path);
/* Link in the object file */ /* Link in the object file */
_loadingBundlePos = [_bundles indexOfObject:self]; _loadingBundlePos = [_bundles indexOfObject:self];
if (objc_load_module([object cString], if (objc_load_module([object cString],
stderr, _bundle_load_callback, NULL, NULL)) { stderr, _bundle_load_callback, NULL, NULL)) {
[NSException raise:NSGenericException [NSException raise:NSGenericException
format:TEMP_STRING("Unable to load module")]; format:@"Unable to load module %s", [object cString]];
/* NOT REACHED */ /* NOT REACHED */
} else } else
_codeLoaded = YES; _codeLoaded = YES;
@ -331,7 +341,7 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
if (!name || [name length] == 0) { if (!name || [name length] == 0) {
[NSException raise:NSInvalidArgumentException [NSException raise:NSInvalidArgumentException
format:TEMP_STRING("No resource name specified.")]; format:@"No resource name specified."];
/* NOT REACHED */ /* NOT REACHED */
} }
@ -339,15 +349,14 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
unsigned i, count; unsigned i, count;
count = [_languages count]; count = [_languages count];
for (i=0; i < count; i++) { for (i=0; i < count; i++) {
path = construct_path(bundlePath, [_languages objectAtIndex:i], path = bundle_resource_path(bundlePath,
name, ext ); [_languages objectAtIndex:i], name, ext );
if ( stat([path cString], &statbuf) == 0) if ( stat([path cString], &statbuf) == 0)
break; break;
path = nil; path = nil;
count++;
} }
} else { } else {
path = construct_path(bundlePath, TEMP_STRING("English"), name, ext ); path = bundle_resource_path(bundlePath, @"English", name, ext );
if ( stat([path cString], &statbuf) != 0) { if ( stat([path cString], &statbuf) != 0) {
path = nil; path = nil;
} }
@ -355,13 +364,12 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
} }
if (!path) { if (!path) {
path = construct_path(bundlePath, nil, name, ext ); path = bundle_resource_path(bundlePath, nil, name, ext );
if ( stat([path cString], &statbuf) != 0) { if ( stat([path cString], &statbuf) != 0) {
path = nil; path = nil;
} }
} }
/* Note: path is already autoreleased */
return path; return path;
} }
@ -390,8 +398,8 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
+ (void)setSystemLanguages:(NSArray *)languages + (void)setSystemLanguages:(NSArray *)languages
{ {
static NSString *separator; static NSString *separator = @" ";
if (!separator) separator = STATIC_STRING(" ");
if (_languages) { if (_languages) {
FREE_OBJECT(_languages); FREE_OBJECT(_languages);
} }
@ -401,7 +409,7 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
string. string.
*/ */
if (!languages) { if (!languages) {
NSString *env = [NSString stringWithCString:getenv("LANGUAGE")]; NSString *env = [NSString stringWithCString:getenv("LANGUAGES")];
if (env && [env length] != 0) if (env && [env length] != 0)
_languages = [[env componentsSeparatedByString:separator] retain]; _languages = [[env componentsSeparatedByString:separator] retain];
} else } else
@ -409,18 +417,4 @@ _bundle_load_callback(Class *theClass, Category *theCategory)
} }
// FIXME: this is here to please IndexedCollection - NSObject doesn't have it
- (int)compare:anotherObject
{
if ([self isEqual:anotherObject])
return 0;
// Ordering objects by their address is pretty useless,
// so subclasses should override this is some useful way.
else if (self > anotherObject)
return 1;
else
return -1;
}
@end @end

View file

@ -81,8 +81,10 @@ _NSFoundationUncaughtExceptionHandler(NSException *exception)
NSString *reason; NSString *reason;
NSException *except; NSException *except;
reason = [[NSString alloc] initWithFormat:format arguments:argList]; // OK?: not in OpenStep docs but is implmented by GNUStep
[reason autorelease]; reason = [NSString stringWithFormat:format arguments:argList];
//reason = [[NSString alloc] initWithFormat:format arguments:argList];
//[reason autorelease];
except = [self exceptionWithName:name reason:reason userInfo:nil]; except = [self exceptionWithName:name reason:reason userInfo:nil];
[except raise]; [except raise];
} }
@ -137,7 +139,7 @@ _NSFoundationUncaughtExceptionHandler(NSException *exception)
- (void)encodeWithCoder:(NSCoder *)aCoder - (void)encodeWithCoder:(NSCoder *)aCoder
{ {
[super encodeWithCoder:aCoder]; //FIXME [super encodeWithCoder:aCoder];
[aCoder encodeObject:e_name]; [aCoder encodeObject:e_name];
[aCoder encodeObject:e_reason]; [aCoder encodeObject:e_reason];
[aCoder encodeObject:e_info]; [aCoder encodeObject:e_info];
@ -145,7 +147,7 @@ _NSFoundationUncaughtExceptionHandler(NSException *exception)
- (id)initWithCoder:(NSCoder *)aDecoder - (id)initWithCoder:(NSCoder *)aDecoder
{ {
self = [super initWithCoder:aDecoder]; //FIXME self = [super initWithCoder:aDecoder];
e_name = [[aDecoder decodeObject] retain]; e_name = [[aDecoder decodeObject] retain];
e_reason = [[aDecoder decodeObject] retain]; e_reason = [[aDecoder decodeObject] retain];
e_info = [[aDecoder decodeObject] retain]; e_info = [[aDecoder decodeObject] retain];

View file

@ -23,7 +23,7 @@
#include <math.h> #include <math.h>
#include <objects/stdobjects.h> #include <objects/stdobjects.h>
#include "NSGeometry.h" #include <foundation/NSGeometry.h>
/* Create Basic Structures */ /* Create Basic Structures */
NSPoint NSPoint

View file

@ -21,39 +21,15 @@
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* #include <foundation/NSConcreteValue.h>
FIXME - Some of NeXT's requirements escape me at this point. Why would #include <foundation/NSCoder.h>
you need to override classForCoder in subclasses? Can we encode void *
or not?
*/
/* xxx This needs fixing because NSValue shouldn't have any
instance variables. -mccallum */
#include "NSValue.h"
#include "NSObjectPrivate.h" /* For standard exceptions */
#include "NSString.h"
#include "NSCoder.h"
#include "object_zone.h" /* Zone mallocing */
#include <objects/stdobjects.h>
#include <string.h>
@implementation NSValue @implementation NSValue
// NSCopying // NSCopying
/* deepening is done by concrete subclasses */
- deepen - deepen
{ {
void *old_ptr;
unsigned size;
size = objc_sizeof_type([objctype cString]);
old_ptr = _dataptr;
_dataptr = (void *)NSZoneMalloc([self zone], size);
NS_CHECK_MALLOC(_dataptr)
memcpy(_dataptr, old_ptr, size);
objctype = [objctype copyWithZone:[self zone]];
return self; return self;
} }
@ -65,137 +41,132 @@
return [[super copyWithZone:zone] deepen]; return [[super copyWithZone:zone] deepen];
} }
// Allocating and Initializing /* Returns the concrete class associated with the type encoding */
+ (Class)valueClassWithObjCType:(const char *)type
/* This method is apperently not in the OpenStep specification, but it makes
subclassing a lot easier */
- initValue:(const void *)value
withObjCType:(const char *)type
{ {
unsigned size; Class theClass = [NSConcreteValue class];
if (!value || !type) { /* Let someone else deal with this error */
[NSException raise:NSInvalidArgumentException if (!type)
format:TEMP_STRING("NULL value or NULL type")]; return theClass;
/* NOT REACHED */
if (strcmp(@encode(id), type) == 0)
theClass = [NSNonretainedObjectValue class];
else if (strcmp(@encode(NSPoint), type) == 0)
theClass = [NSPointValue class];
else if (strcmp(@encode(void *), type) == 0)
theClass = [NSPointerValue class];
else if (strcmp(@encode(NSRect), type) == 0)
theClass = [NSRectValue class];
else if (strcmp(@encode(NSSize), type) == 0)
theClass = [NSSizeValue class];
return theClass;
} }
// FIXME: objc_sizeof_type will abort when it finds an invalid type, when // Allocating and Initializing
// we really want to just raise an exception
size = objc_sizeof_type(type);
if (size <= 0) {
[NSException raise:NSInternalInconsistencyException
format:TEMP_STRING("Invalid Objective-C type")];
/* NOT REACHED */
}
_dataptr = (void *)NSZoneMalloc([self zone], size);
NS_CHECK_MALLOC(_dataptr)
memcpy(_dataptr, value, size);
objctype = [[NSString stringWithCString:type] retain];
return self;
}
+ (NSValue *)value:(const void *)value + (NSValue *)value:(const void *)value
withObjCType:(const char *)type withObjCType:(const char *)type
{ {
return [[[self alloc] initValue:value withObjCType:type] autorelease]; Class theClass = [self valueClassWithObjCType:type];
return [[[theClass alloc] initValue:value withObjCType:type]
autorelease];
} }
+ (NSValue *)valueWithNonretainedObject: (id)anObject + (NSValue *)valueWithNonretainedObject: (id)anObject
{ {
return [self value:&anObject withObjCType:@encode(id)]; return [[[NSNonretainedObjectValue alloc]
initValue:&anObject withObjCType:@encode(id)]
autorelease];
} }
+ (NSValue *)valueWithPoint:(NSPoint)point + (NSValue *)valueWithPoint:(NSPoint)point
{ {
return [self value:&point withObjCType:@encode(NSPoint)]; return [[[NSPointValue alloc]
initValue:&point withObjCType:@encode(NSPoint)]
autorelease];
} }
+ (NSValue *)valueWithPointer:(const void *)pointer + (NSValue *)valueWithPointer:(const void *)pointer
{ {
return [self value:&pointer withObjCType:@encode(void *)]; return [[[NSPointerValue alloc]
initValue:&pointer withObjCType:@encode(void*)]
autorelease];
} }
+ (NSValue *)valueWithRect:(NSRect)rect + (NSValue *)valueWithRect:(NSRect)rect
{ {
return [self value:&rect withObjCType:@encode(NSRect)]; return [[[NSRectValue alloc] initValue:&rect withObjCType:@encode(NSRect)]
autorelease];
} }
+ (NSValue *)valueWithSize:(NSSize)size + (NSValue *)valueWithSize:(NSSize)size
{ {
return [self value:&size withObjCType:@encode(NSSize)]; return [[[NSSizeValue alloc] initValue:&size withObjCType:@encode(NSSize)]
} autorelease];
- (void)dealloc
{
[objctype release];
NSZoneFree([self zone], _dataptr);
[super dealloc];
} }
// Accessing Data // Accessing Data
/* All the rest of these methods must be implemented by a subclass */
- (void)getValue:(void *)value - (void)getValue:(void *)value
{ {
if (!value) { [self doesNotRecognizeSelector:_cmd];
[NSException raise:NSInvalidArgumentException
format:TEMP_STRING("Cannot copy value into NULL buffer")];
/* NOT REACHED */
}
memcpy( value, _dataptr, objc_sizeof_type([objctype cString]) );
} }
- (const char *)objCType - (const char *)objCType
{ {
return [objctype cString]; [self doesNotRecognizeSelector:_cmd];
return 0;
} }
// FIXME: need to check to make sure these hold the right values... // FIXME: Is this an error or an exception???
- (id)nonretainedObjectValue - (id)nonretainedObjectValue
{ {
return *((id *)_dataptr); [self doesNotRecognizeSelector:_cmd];
return 0;
} }
- (void *)pointerValue - (void *)pointerValue
{ {
return *((void **)_dataptr); [self doesNotRecognizeSelector:_cmd];
return 0;
} }
- (NSRect)rectValue - (NSRect)rectValue
{ {
return *((NSRect *)_dataptr); [self doesNotRecognizeSelector:_cmd];
return NSMakeRect(0,0,0,0);
} }
- (NSSize)sizeValue - (NSSize)sizeValue
{ {
return *((NSSize *)_dataptr); [self doesNotRecognizeSelector:_cmd];
return NSMakeSize(0,0);
} }
- (NSPoint)pointValue - (NSPoint)pointValue
{ {
return *((NSPoint *)_dataptr); [self doesNotRecognizeSelector:_cmd];
return NSMakePoint(0,0);
}
// NSCoding (done by subclasses)
- classForCoder
{
return [self class];
} }
// NSCoding
- (void)encodeWithCoder:(NSCoder *)coder - (void)encodeWithCoder:(NSCoder *)coder
{ {
//FIXME [super encodeWithCoder:coder];
[super encodeWithCoder:coder];
// FIXME: Do we need to check for encoding void, void * or will
// NSCoder do this for us?
[coder encodeObject:objctype];
[coder encodeValueOfObjCType:[objctype cString] at:&_dataptr];
} }
- (id)initWithCoder:(NSCoder *)coder - (id)initWithCoder:(NSCoder *)coder
{ {
self = [super initWithCoder:coder]; //FIXME self = [super initWithCoder:coder];
objctype = [[coder decodeObject] retain];
[coder decodeValueOfObjCType:[objctype cString] at:&_dataptr];
return self; return self;
} }
@end @end

View file

@ -273,6 +273,11 @@
return @encode(char); return @encode(char);
} }
- (const char *) contentType
{
return @encode(char);
}
- (int(*)(elt,elt)) comparisonFunction - (int(*)(elt,elt)) comparisonFunction
{ {
return elt_compare_chars; return elt_compare_chars;