From f88a65db7ee41ca77540bd83ba2c2094f58c49e8 Mon Sep 17 00:00:00 2001 From: fedor Date: Mon, 29 Sep 1997 14:39:53 +0000 Subject: [PATCH] Rewrite of NSData from Richard Frith-Macdonald git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@2459 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 90 ++ Headers/gnustep/base/MemoryStream.h | 21 +- Headers/gnustep/base/NSConnection.h | 2 +- Headers/gnustep/base/NSData.h | 40 +- Headers/gnustep/base/NSDistantObject.h | 2 +- Headers/gnustep/base/NSGData.h | 67 - Headers/gnustep/base/NSHData.h | 227 ---- Headers/gnustep/base/NSObject.h | 2 +- Headers/gnustep/base/NSPortCoder.h | 2 +- Source/Coder.m | 13 +- Source/Invocation.m | 10 +- Source/Makefile | 4 - Source/MemoryStream.m | 195 ++- Source/NSAttributedString.m | 2 +- Source/NSData.m | 1358 +++++++++++++++---- Source/NSDate.m | 2 +- Source/NSDistantObject.m | 15 +- Source/NSGArchiver.m | 16 +- Source/NSGAttributedString.m | 4 +- Source/NSGCString.m | 2 +- Source/NSGData.m | 166 --- Source/NSGString.m | 2 +- Source/NSHData.m | 1684 ------------------------ Source/NSPortCoder.m | 21 +- Source/NSString.m | 2 +- Source/Port.m | 2 +- Source/StdioStream.m | 7 +- Source/TcpPort.m | 25 +- Source/UdpPort.m | 2 +- Source/UnixFileHandle.m | 118 +- Testing/nsdata.m | 72 + Testing/oldserver.h | 4 +- 32 files changed, 1576 insertions(+), 2603 deletions(-) delete mode 100644 Headers/gnustep/base/NSGData.h delete mode 100644 Headers/gnustep/base/NSHData.h delete mode 100644 Source/NSGData.m delete mode 100644 Source/NSHData.m diff --git a/ChangeLog b/ChangeLog index 0bb20b48c..18af2cb5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,93 @@ +Sun Sep 28 21:15:00 1997 Richard Frith-Macdonald + + * checks/nsdata.m: Added a whole lot of trivial checks. + + * checks/oldserver.h: Added include file for oldserver.m, oldclient.m + + * src/Coder.m: ([-initForWritingWithMutableData:]) added code to + wrap the NSMutableData object inside a MemoryStream since + NSMutableData no longer conforms to the MemoryStreaming protocol. + ([-initForReadingWithData:]) added code to wrap the NSData object + inside a MemoryStream. + ([+unarchiveObjectWithData:]) added code to wrap the NSData object + inside a MemoryStream. + ([-classForPortCoder:]) changed to [-classForPortCoder] to conform + to OpenStep spec. + + * src/Makefile.in: Removed NSGData.[hm] and NSHData.[hm] + + * src/MemoryStream.m: Rewritten to use NSData and NSMutableData + objects to hold the memory. + + * src/NSAttributedString.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/NSData.m: Extensively rewritten to have the OPENSTEP class + cluster architecture. Should support the full OPENSTEP api and + have shared memory support and static buffer support as extensions. + + * src/NSDate.m: ([-classForPortCoder:]) changed to [-classForPortCoder] + to conform to OpenStep spec. + + * src/NSDistantObject.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/NSGArchiver.m: ([-archiverData]) modified to cope with changes + to NSData and NSMutableData. + + * src/NSGAttributedString.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/NSGCString.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/NSGString.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/NSPortCoder.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + ([-isByCopy]) changed to [-isBycopy] to conform to OpenStep. + + * src/NSString.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/Port.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/StdioStream.m: ([-initWithFilename:fmode:]) fixed excessive + releases of string. ([-initWithFileDescriptor:fmode:]) fixed + excessive releases of string. ([-close]) clear file pointer when + it is closed to prevent attempted operations on bad pointer. + + * src/TcpPort.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. Also multiple + changes to deal with the rewrite of MemoryStream. + + * src/UdpPort.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/UnixFileHandle.m: Numerous changes improving logging and + tidying stuff. failed initialisers should now all return nil + rather than raising exceptions. + + * src/include/MemoryStream.h: Changed this class to use NSData and + NSMutableData to hold its contents. Added methods to initialise + with a data object so we can wrap an NSData or NSMutableData inside + a MemoryStream to give it Streaming behaviour. + + * src/include/NSData.h: Added some extension methods for creating + data objects with static buffers or shared memory buffers. + + * src/include/NSDistantObject.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/include/NSObject.m: ([-classForPortCoder:]) changed to + [-classForPortCoder] to conform to OpenStep spec. + + * src/include/NSPortCoder.m: ([-classForPortCoder:]) changed to + [-classForPortCoder], and ([-isByCopy]) changed to [-isBycopy] to + conform to OpenStep spec. + Fri Sep 26 20:43:12 1997 Adam Fedor * Fix Makefiles so snapshots and releases work again diff --git a/Headers/gnustep/base/MemoryStream.h b/Headers/gnustep/base/MemoryStream.h index 2ec54f76c..34693c78d 100644 --- a/Headers/gnustep/base/MemoryStream.h +++ b/Headers/gnustep/base/MemoryStream.h @@ -21,6 +21,13 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + Modified by: Richard Frith-Macdonald + Date: September 1997 + + Modifications to use NSData and NSMutable data objects to hold data. +*/ + #ifndef __MemoryStream_h_GNUSTEP_BASE_INCLUDE #define __MemoryStream_h_GNUSTEP_BASE_INCLUDE @@ -45,21 +52,23 @@ @interface MemoryStream : Stream { - int type; - char *buffer; - int size; - int eof_position; + id data; int prefix; int position; - BOOL free_when_done; + int eof_position; + BOOL isMutable; } ++ (MemoryStream*)streamWithData: (id)anObject; + - initWithCapacity: (unsigned)capacity prefix: (unsigned)prefix; +- initWithData: (id)anObject; - initWithSize: (unsigned)s; /* For backwards compatibility, depricated */ -- (void) setFreeWhenDone: (BOOL)f; +- (id) data; +- (id) mutableData; - (unsigned) streamBufferPrefix; - (unsigned) streamBufferLength; /* prefix + eofPosition */ diff --git a/Headers/gnustep/base/NSConnection.h b/Headers/gnustep/base/NSConnection.h index 276b4cda5..66af2faaa 100644 --- a/Headers/gnustep/base/NSConnection.h +++ b/Headers/gnustep/base/NSConnection.h @@ -258,7 +258,7 @@ extern NSString *ConnectionBecameInvalidNotification; @end @interface Object (NSPortCoder) -- (Class) classForPortCoder: (NSPortCoder*)aCoder; +- (Class) classForPortCoder; /* * Must return the class that will be created on the remote side * of the connection. If the class to be created is not the same diff --git a/Headers/gnustep/base/NSData.h b/Headers/gnustep/base/NSData.h index e8eb49bfd..c42057c0b 100644 --- a/Headers/gnustep/base/NSData.h +++ b/Headers/gnustep/base/NSData.h @@ -34,13 +34,13 @@ + (id)data; + (id)dataWithBytes: (const void*)bytes - length: (unsigned int)length; + length: (unsigned int)length; + (id)dataWithBytesNoCopy: (void*)bytes - length: (unsigned int)length; + length: (unsigned int)length; + (id)dataWithContentsOfFile: (NSString*)path; + (id)dataWithContentsOfMappedFile: (NSString*)path; - (id)initWithBytes: (const void*)bytes - length: (unsigned int)length; + length: (unsigned int)length; - (id)initWithBytesNoCopy: (void*)bytes length: (unsigned int)length; - (id)initWithContentsOfFile: (NSString*)path; @@ -53,9 +53,9 @@ - (NSString*)description; - (void)getBytes: (void*)buffer; - (void)getBytes: (void*)buffer - length: (unsigned int)length; + length: (unsigned int)length; - (void)getBytes: (void*)buffer - range: (NSRange)aRange; + range: (NSRange)aRange; - (NSData*)subdataWithRange: (NSRange)aRange; // Querying a Data Object @@ -72,23 +72,29 @@ - (unsigned int)deserializeAlignedBytesLengthAtCursor: (unsigned int*)cursor; - (void)deserializeBytes: (void*)buffer - length: (unsigned int)bytes - atCursor: (unsigned int*)cursor; + length: (unsigned int)bytes + atCursor: (unsigned int*)cursor; - (void)deserializeDataAt: (void*)data - ofObjCType: (const char*)type - atCursor: (unsigned int*)cursor - context: (id )callback; + ofObjCType: (const char*)type + atCursor: (unsigned int*)cursor + context: (id )callback; - (int)deserializeIntAtCursor: (unsigned int*)cursor; - (int)deserializeIntAtIndex: (unsigned int)location; - (void)deserializeInts: (int*)intBuffer - count: (unsigned int)numInts - atCursor: (unsigned int*)cursor; + count: (unsigned int)numInts + atCursor: (unsigned int*)cursor; - (void)deserializeInts: (int*)intBuffer - count: (unsigned int)numInts - atIndex: (unsigned int)index; + count: (unsigned int)numInts + atIndex: (unsigned int)index; @end +@interface NSData (GNUstepExtensions) ++ (id) dataWithShmID: (int)anID length: (unsigned) length; ++ (id) dataWithSharedBytes: (const void*)bytes length: (unsigned) length; ++ (id) dataWithStaticBytes: (const void*)bytes length: (unsigned) length; +@end + @interface NSMutableData : NSData @@ -132,6 +138,12 @@ @end +@interface NSMutableData (GNUstepExtensions) +- (unsigned int) capacity; +- (id) setCapacity: (unsigned int)newCapacity; +- (int) shmID; +@end + /* Local Variables: mode: ObjC diff --git a/Headers/gnustep/base/NSDistantObject.h b/Headers/gnustep/base/NSDistantObject.h index cfeaa12ff..557601413 100644 --- a/Headers/gnustep/base/NSDistantObject.h +++ b/Headers/gnustep/base/NSDistantObject.h @@ -55,7 +55,7 @@ + newForRemoteTarget: (unsigned)target connection: (NSConnection*)conn; - awakeAfterUsingCoder: aDecoder; -- classForPortCoder: aRmc; +- classForPortCoder; + newWithCoder: aRmc; - (const char *) selectorTypeForProxy: (SEL)selector; - forward: (SEL)aSel :(arglist_t)frame; diff --git a/Headers/gnustep/base/NSGData.h b/Headers/gnustep/base/NSGData.h deleted file mode 100644 index 47caa4cbb..000000000 --- a/Headers/gnustep/base/NSGData.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Interface to concrete implementation of NSData based on MemoryStream class - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by: Andrew Kachites McCallum - Date: April 1995 - - This file is part of the GNUstep Base Library. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - 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. - */ - -#ifndef __NSGData_h_GNUSTEP_BASE_INCLUDE -#define __NSGData_h_GNUSTEP_BASE_INCLUDE - -#include -#include -#include - -@interface NSGData : NSData -{ - /* For now, these must match the instance variables in - gnustep/base/MemoryStream.h. - This will change. */ - int type; - char *buffer; - int size; - int eofPosition; - int prefix; - int position; -} - -@end - -@interface NSGData (GNU) -@end - -@interface NSGMutableData : NSMutableData -{ - /* For now, these must match the instance variables in - gnustep/base/MemoryStream.h. - This will change. */ - int type; - char *buffer; - int size; - int eofPosition; - int prefix; - int position; -} - -@end - -@interface NSGMutableData (GNU) -@end - -#endif /* __NSGData_h_GNUSTEP_BASE_INCLUDE */ diff --git a/Headers/gnustep/base/NSHData.h b/Headers/gnustep/base/NSHData.h deleted file mode 100644 index 54361f0cd..000000000 --- a/Headers/gnustep/base/NSHData.h +++ /dev/null @@ -1,227 +0,0 @@ -/* Interface for GNU Objective C NSData classes - Copyright (C) 1997 Free Software Foundation, Inc. - - Written by: Richard Frith-Macdonald - Date: July 1997 - - This file is part of the GNUstep Base Library. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - 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. - */ - -#ifndef __NSHData_h -#define __NSHData_h - -#include -#include -#include -#include -#include -#include -#include - -typedef enum { - MALLOC_DATA = 0, // This is data allocated by malloc. - STATIC_DATA, // This is data from somewhere else. - SHARED_DATA, // This is data allocated by shmget. - MAPPED_DATA // This is a memory mapped file. -} NSDataType; - -@interface NSHData : NSData -{ - NSDataType type; - char* buffer; - int shm_id; - unsigned int size; - unsigned int eof_position; - unsigned int position; -} - -+ (id) data; -+ (id) dataWithBytes: (const void*)bytes - length: (unsigned int)length; -+ (id) dataWithBytesNoCopy: (void*)bytes - length: (unsigned int)length; -+ (id) dataWithContentsOfFile: (NSString*)path; -+ (id) dataWithContentsOfMappedFile: (NSString*)path; -+ (id) dataWithData: (NSData*)other; - -- (const void*)bytes; -- (NSString*) description; -- (void) getBytes: (void*)buffer; -- (void) getBytes: (void*)buffer - length: (unsigned int)length; -- (void) getBytes: (void*)buffer - range: (NSRange)aRange; - -- (id) initWithBytes: (const void*)bytes - length: (unsigned int)length; -- (id) initWithBytesNoCopy: (void*)bytes - length: (unsigned int)length; -- (id) initWithContentsOfFile: (NSString*)path; -- (id) initWithContentsOfMappedFile: (NSString*)path; -- (id) initWithData: (NSData*)data; - -- (BOOL) isEqualToData: (NSData*)other; -- (unsigned int) length; -- (NSData*)subdataWithRange: (NSRange)aRange; -- (BOOL) writeToFile: (NSString*)path - atomically: (BOOL)useAuxiliaryFile; - - -- (unsigned int) deserializeAlignedBytesLengthAtCursor: (unsigned int*)cursor; -- (void) deserializeBytes: (void*)buffer - length: (unsigned int)bytes - atCursor: (unsigned int*)cursor; -- (void) deserializeDataAt: (void*)data - ofObjCType: (const char*)type - atCursor: (unsigned int*)cursor - context: (id )callback; -- (int) deserializeIntAtCursor: (unsigned int*)cursor; -- (int) deserializeIntAtIndex: (unsigned int)location; -- (void) deserializeInts: (int*)intBuffer - count: (unsigned int)numInts - atCursor: (unsigned int*)cursor; -- (void) deserializeInts: (int*)intBuffer - count: (unsigned int)numInts - atIndex: (unsigned int)index; - - -/* GNUstep extensions to NSData primarily for the Streaming prototcol. - The write operations have no effect on an NSData but work as expected - for NSMutableData objects. - */ -+ (void) setVMChunk:(int)size; -+ (void) setVMThreshold:(int)size; -+ (int) vmChunk; -+ (int) vmThreshold; -- (void) close; -- (void) flushStream; - -/* How the internal designated initialiser works - - if 't' is MALLOC_DATA - if 'f' is YES - We set 'buffer' to 'b' - else - We set 'buffer' to point to memory allocated of the size - specified in 's', and copy 'l' bytes from 'b' or clear - 'l' bytes if 'b' is nul. We set 'f' to YES. - - if 't' is STATIC_DATA - If 'b' is zero - We set 'buffer' to "" and set 'size' to zero. - else - We set 'buffer' to 'b' - - if 't' is SHARED_DATA - If 'm' is non-zero - We attach to the specified chunk of shared memory and set - 'buffer' to point to it. We set 'size' to the size of the - shared memory. We either clear the first 'l' bytes or we - copy them from 'b' if 'b' is not nul. - else - We create a chunk of shared memory of at least 'size' bytes, - set 'buffer' to point to it, and set 'size' to the size of - the shared memory. - We either clear the first 'l' bytes or we copy them from 'b' - if 'b' is not nul. - - if 't' is MAPPED_DATA - We map the file 'n' into memory and set 'buffer' to point to it. - - */ -- initOnBuffer: (void*)b /* data area or nul pointer */ - size: (unsigned)s /* size of the data area */ - type: (NSDataType)t /* type of storage to use */ - sharedMem: (int)m /* ID of shared memory segment */ - fileName: (NSString*)n /* name of mmap file. */ - eofPosition: (unsigned)l /* length of data for reading */ - position: (unsigned)i /* current pos for read/write */ - noCopy: (BOOL)f; - -- initWithCapacity: (unsigned int)capacity; -- (BOOL) isAtEof; -- (BOOL) isClosed; -- (BOOL) isWritable; - -- (int) readByte: (unsigned char*)b; -- (int) readBytes: (void*)b length: (int)l; -- (int) readFormat: (NSString*)format, ...; -- (int) readFormat: (NSString*)format arguments: (va_list)arg; -- (NSString*) readLine; - -- (void) rewindStream; - -- (void) setFreeWhenDone: (BOOL)f; -- (void) setStreamBufferCapacity: (unsigned)s; -- (void) setStreamEofPosition: (unsigned)i; -- (void) setStreamPosition: (unsigned)i; -- (void) setStreamPosition: (unsigned)i seekMode: (seek_mode_t)mode; -- (void) setVMThreshold:(int)size; - -- (char*) streamBuffer; /* Returns null for an NSData object. */ -- (unsigned) streamBufferLength; -- (unsigned) streamEofPosition; -- (unsigned) streamPosition; - -/* The following write operations have no effect on an NSData object. */ -- (int) writeByte: (unsigned char)b; -- (int) writeBytes: (const void*)b length: (int)l; -- (int) writeFormat: (NSString*)format, ...; -- (int) writeFormat: (NSString*)format arguments: (va_list)arg; -- (void) writeLine: (NSString*)l; - -- (int) vmThreshold; -@end - -@interface NSHMutableData : NSHData -{ - int vm_threshold; -} - -+ (id) dataWithCapacity: (unsigned int)numBytes; -+ (id) dataWithLength: (unsigned int)length; - -- (void) appendBytes:(const void*)bytes - length:(unsigned int)length; -- (void) appendData:(NSData*)other; -- (void) increaseLengthBy:(unsigned int)length; -- (id) initWithLength: (unsigned int)length; -- (void*) mutableBytes; -- (void) replaceBytesInRange: (NSRange)aRange - withBytes: (const void*)bytes; -- (void) resetBytesInRange: (NSRange)aRange; -- (void) setData:(NSData*)other; -- (void) setLength:(unsigned int)length; -- (void) setVMThreshold:(int)size; - -- (void) serializeAlignedBytesLength: (unsigned int)length; -- (void) serializeDataAt: (const void*)data - ofObjCType: (const char*)type - context: (id )callback; -- (void) serializeInt: (int)value; -- (void) serializeInt: (int)value - atIndex: (unsigned int)location; -- (void) serializeInts: (int*)intBuffer - count: (unsigned int)numInts; -- (void) serializeInts: (int*)intBuffer - count: (unsigned int)numInts - atIndex: (unsigned int)location; - -- (int) vmThreshold; -- (void) increaseCapacityBy:(unsigned int)length; -@end - -#endif /* __NSHData_h */ diff --git a/Headers/gnustep/base/NSObject.h b/Headers/gnustep/base/NSObject.h index 1ff1a8a83..3bdcdd102 100644 --- a/Headers/gnustep/base/NSObject.h +++ b/Headers/gnustep/base/NSObject.h @@ -114,7 +114,7 @@ @end @interface NSObject (NSPortCoder) -- (Class) classForPortCoder: (NSPortCoder*)anEncoder; +- (Class) classForPortCoder; - (id) replacementObjectForPortCoder: (NSPortCoder*)anEncoder; @end diff --git a/Headers/gnustep/base/NSPortCoder.h b/Headers/gnustep/base/NSPortCoder.h index 273566ed7..6129a44bd 100644 --- a/Headers/gnustep/base/NSPortCoder.h +++ b/Headers/gnustep/base/NSPortCoder.h @@ -39,7 +39,7 @@ - (NSConnection*) connection; - (NSPort*) decodePortObject; - (void) encodePortObject: (NSPort*)aPort; -- (BOOL) isByCopy; +- (BOOL) isBycopy; @end diff --git a/Source/Coder.m b/Source/Coder.m index 25ee0dbf3..be8a5dfe8 100644 --- a/Source/Coder.m +++ b/Source/Coder.m @@ -252,20 +252,16 @@ static BOOL debug_coder = NO; /* Initializing an archiver */ -@interface NSData (Streaming) -@end - - (id) initForWritingWithMutableData: (NSMutableData*)mdata { - /* This relies on the fact that GNU extentions to NSMutableData - cause it to conform to . */ - [(id)self initForWritingToStream: mdata]; + [(id)self initForWritingToStream: [MemoryStream streamWithData: mdata]]; return self; } - (id) initForReadingWithData: (NSData*)data { - id ret = [[self class] newReadingFromStream: data]; + id ret = [[self class] newReadingFromStream: + [MemoryStream streamWithData:data]]; if ([self retainCount] == 0) [ret autorelease]; else @@ -295,7 +291,8 @@ static BOOL debug_coder = NO; + unarchiveObjectWithData: (NSData*) data { - return [self decodeObjectWithName: NULL fromStream: data]; + return [self decodeObjectWithName: NULL + fromStream: [MemoryStream streamWithData:data]]; } + unarchiveObjectWithFile: (NSString*) path diff --git a/Source/Invocation.m b/Source/Invocation.m index 2ed6d3d10..ff8ce6f1a 100644 --- a/Source/Invocation.m +++ b/Source/Invocation.m @@ -118,7 +118,7 @@ } /* Next two methods for OPENSTEP */ -- (Class) classForPortCoder: coder +- (Class) classForPortCoder { return [self class]; } @@ -753,9 +753,9 @@ my_method_get_next_argument (arglist_t argframe, /* Encode ourself as a proxies across Connection's; we can't encode a function across the wire. */ -- classForPortCoder: coder +- classForPortCoder { - return [[coder connection] proxyClass]; + return [NSDistantObject class]; } - (void) encodeWithCoder: (id )coder @@ -786,9 +786,9 @@ my_method_get_next_argument (arglist_t argframe, /* Encode ourself as a proxies across Connection's; we can't encode a function across the wire. */ -- classForPortCoder: coder +- classForPortCoder { - return [[coder connection] proxyClass]; + return [NSDistantObject class]; } - (void) encodeWithCoder: (id )coder diff --git a/Source/Makefile b/Source/Makefile index a391e0cad..71a304aad 100644 --- a/Source/Makefile +++ b/Source/Makefile @@ -315,8 +315,6 @@ NSGArray.m \ NSGAttributedString.m \ NSGCountedSet.m \ NSGCString.m \ -NSGData.m \ -NSHData.m \ NSGDictionary.m \ NSGSet.m \ NSGSequence.m \ @@ -406,8 +404,6 @@ Foundation/NSGArchiver.h \ Foundation/NSGArray.h \ Foundation/NSGAttributedString.h \ Foundation/NSGCString.h \ -Foundation/NSGData.h \ -Foundation/NSHData.h \ Foundation/NSGDictionary.h \ Foundation/NSGSet.h \ Foundation/NSGSequence.h \ diff --git a/Source/MemoryStream.m b/Source/MemoryStream.m index 003da351d..4bf979fe3 100644 --- a/Source/MemoryStream.m +++ b/Source/MemoryStream.m @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -44,15 +45,6 @@ /* memory.h and strings.h conflict on some systems. */ #endif /* not STDC_HEADERS and not HAVE_STRING_H */ -/* This could be done with a set of classes instead. */ -enum {MALLOC_MEMORY_STREAM = 0, OBSTACK_MEMORY_STREAM, VM_MEMORY_STREAM}; - -enum { - STREAM_READONLY = 0, - STREAM_READWRITE, - STREAM_WRITEONLY -}; - #define DEFAULT_MEMORY_STREAM_SIZE 64 extern int @@ -67,6 +59,16 @@ static BOOL debug_memory_stream = NO; @implementation MemoryStream ++ (MemoryStream*)streamWithData: (id)anObject +{ + return [[[MemoryStream alloc] initWithData:anObject] autorelease]; +} + +- (id) data +{ + return data; +} + /* xxx This interface will change */ - _initOnMallocBuffer: (char*)b freeWhenDone: (BOOL)f @@ -75,14 +77,37 @@ static BOOL debug_memory_stream = NO; prefix: (unsigned)p /* never read/write before this position */ position: (unsigned)i /* current position for reading/writing */ { - [super init]; - buffer = b; - size = s; - prefix = p; - position = i; - eof_position = l; - free_when_done = f; - type = MALLOC_MEMORY_STREAM; + self = [super init]; + if (self) + { + if (b) + if (f) + data = [NSMutableData dataWithBytesNoCopy: b length: s]; + else + data = [NSMutableData dataWithBytes: b length: s]; + else + { + data = [NSMutableData dataWithCapacity: s]; + if (data) + [data setLength: s]; + } + + if (data) + { + [data retain]; + prefix = p; + position = i; + eof_position = l; + isMutable = YES; + if ([data length] < prefix + MAX(position, eof_position)) + [data setLength: prefix + MAX(position, eof_position)]; + } + else + { + [self release]; + self = nil; + } + } return self; } @@ -105,9 +130,7 @@ static BOOL debug_memory_stream = NO; prefix: (unsigned)p position: (unsigned)i { - char *b; - OBJC_MALLOC(b, char, s); - return [self _initOnMallocBuffer:b + return [self _initOnMallocBuffer: 0 freeWhenDone: YES size: s eofPosition: i @@ -128,6 +151,29 @@ static BOOL debug_memory_stream = NO; return [self initWithSize:capacity prefix:0 position:0]; } +- initWithData: (id)anObject +{ + self = [super init]; + if (self) + { + if (anObject && [anObject isKindOfClass:[NSData class]]) + { + data = [anObject retain]; + if ([data isKindOfClass:[NSMutableData class]]) + isMutable = YES; + eof_position = [data length]; + position = 0; + prefix = 0; + } + else + { + [self dealloc]; + self = nil; + } + } + return self; +} + - initWithSize: (unsigned)s { return [self initWithCapacity:s]; @@ -138,14 +184,9 @@ static BOOL debug_memory_stream = NO; return [self initWithCapacity: DEFAULT_MEMORY_STREAM_SIZE]; } -- (void) setFreeWhenDone: (BOOL)f -{ - free_when_done = f; -} - - (BOOL) isWritable { - return YES; + return isMutable; } - (void) encodeWithCoder: anEncoder @@ -159,38 +200,54 @@ static BOOL debug_memory_stream = NO; return self; } +- (id) mutableData +{ + if (isMutable) + return data; + return nil; +} + - (int) writeBytes: (const void*)b length: (int)l { - if (prefix+position+l > size) + unsigned size; + + if (isMutable) { - size = MAX(prefix+position+l, size*2); - buffer = objc_realloc (buffer, size); + size = [data capacity]; + if (prefix+position+l > size) + { + size = MAX(prefix+position+l, size*2); + [data setCapacity: size]; + } + if (position+prefix+l > [data length]) + [data setLength: position+prefix+l]; + memcpy([data mutableBytes]+prefix+position, b, l); + position += l; + if (position > eof_position) + eof_position = position; + return l; } - memcpy(buffer+prefix+position, b, l); - position += l; - if (position > eof_position) - eof_position = position; - return l; + return 0; } - (int) readBytes: (void*)b length: (int)l { if (position+l > eof_position) l = eof_position-position; - memcpy(b, buffer+prefix+position, l); + memcpy(b, [data bytes]+prefix+position, l); position += l; return l; } - (NSString*) readLine { - char *nl = memchr(buffer+prefix+position, '\n', eof_position-position); + char *nl = memchr([data bytes]+prefix+position, '\n', eof_position-position); char *ret = NULL; if (nl) { - int len = nl-buffer-prefix-position; + int len = nl-((char*)[data bytes])-prefix-position; ret = objc_malloc (len+1); - strncpy(ret, buffer+prefix+position, len); + strncpy(ret, ((char*)[data bytes])+prefix+position, len); ret[len] = '\0'; position += len+1; } @@ -206,54 +263,65 @@ static BOOL debug_memory_stream = NO; int outchar_func(void *s, int c) { - if (MS->prefix + MS->position >= MS->size) - return EOF; - MS->buffer[MS->prefix + MS->position++] = (char)c; - return 1; + if (MS->isMutable) + { + if (MS->prefix + MS->position >= [MS->data capacity]) + return EOF; + ((char*)[MS->data mutableBytes])[MS->prefix + MS->position++] = (char)c; + return 1; + } + return EOF; } int inchar_func(void *s) { - if (MS->prefix + MS->position >= MS->size) + if (MS->prefix + MS->position >= [MS->data length]) return EOF; - return (int) MS->buffer[MS->prefix + MS->position++]; + return (int) ((char*)[MS->data bytes])[MS->prefix + MS->position++]; } void unchar_func(void *s, int c) { if (MS->position > 0) MS->position--; - MS->buffer[MS->prefix + MS->position] = (char)c; + if (MS->isMutable) + ((char*)[MS->data mutableBytes])[MS->prefix + MS->position] = (char)c; } #if HAVE_VSPRINTF - (int) writeFormat: (NSString*)format arguments: (va_list)arg -{ +{ + unsigned size; int ret; + if (!isMutable) + return 0; /* xxx Using this ugliness we at least let ourselves safely print formatted strings up to 128 bytes long. It's digusting, though, and we need to fix it. Using GNU stdio streams would do the trick. */ + size = [data capacity]; if (size - (prefix + position) < 128) - [self setStreamBufferCapacity: MAX(128, size*2)]; - - ret = VSPRINTF_LENGTH (vsprintf(buffer+prefix+position, - [format cStringNoCopy], arg)); + size = MAX(size+128, size*2); + [data setLength: size]; + + ret = VSPRINTF_LENGTH (vsprintf([data mutableBytes]+prefix+position, + [format cStringNoCopy], arg)); position += ret; /* xxx Make sure we didn't overrun our buffer. As per above kludge, this would happen if we happen to have more than 128 bytes left in the buffer and we try to write a string longer than the num bytes left in the buffer. */ - assert(prefix + position <= size); + assert(prefix + position <= [data capacity]); if (position > eof_position) eof_position = position; + [data setLength:eof_position + prefix]; if (debug_memory_stream) { - *(buffer+prefix+position) = '\0'; - fprintf(stderr, "%s\n", buffer+prefix); + *(char*)([data mutableBytes]+prefix+position) = '\0'; + fprintf(stderr, "%s\n", (char*)[data mutableBytes]+prefix); } return ret; } @@ -299,8 +367,7 @@ void unchar_func(void *s, int c) - (void) dealloc { - if (free_when_done) - OBJC_FREE(buffer); + [data release]; [super dealloc]; } @@ -314,21 +381,23 @@ void unchar_func(void *s, int c) - (unsigned) streamBufferCapacity { - return size; + if (isMutable) + return [data capacity]; + return [data length]; } - (char*) streamBuffer { - return buffer; + if (isMutable) + return (char*)[data mutableBytes]; + return 0; } - (void) setStreamBufferCapacity: (unsigned)s { - if (s > prefix + eof_position) - { - buffer = objc_realloc (buffer, s); - size = s; - } + if (isMutable) + if (s > prefix + eof_position) + [data setCapacity:s]; } - (unsigned) streamEofPosition @@ -338,7 +407,7 @@ void unchar_func(void *s, int c) - (void) setStreamEofPosition: (unsigned)i { - if (i < size) + if (i < [data length] - prefix) eof_position = i; } diff --git a/Source/NSAttributedString.m b/Source/NSAttributedString.m index 83a74d738..0855141e1 100644 --- a/Source/NSAttributedString.m +++ b/Source/NSAttributedString.m @@ -102,7 +102,7 @@ static Class NSMutableAttributedString_concrete_class; return [super initWithCoder:aDecoder]; } -- (Class) classForPortCoder: (NSPortCoder*)aCoder +- (Class) classForPortCoder { return [self class]; } diff --git a/Source/NSData.m b/Source/NSData.m index dd932369d..6320bb20e 100644 --- a/Source/NSData.m +++ b/Source/NSData.m @@ -1,8 +1,10 @@ /* Stream of bytes class for serialization and persistance in GNUStep - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. Written by: Andrew Kachites McCallum Date: March 1995 + Rewritten by: Richard Frith-Macdonald + Date: September 1997 This file is part of the GNUstep Base Library. @@ -21,149 +23,84 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* NOTES - Richard Frith-Macdonald 1997 + * + * Rewritten to use the class cluster architecture as in OPENSTEP. + * + * NB. In our implementaion we require an extra primitive for the + * NSMutableData subclasses. This new primitive method is the + * [-setCapacity:] method, and it differs from [-setLength:] + * as follows - + * + * [-setLength:] + * clears bytes when the allocated buffer grows + * never shrinks the allocated buffer capcity + * [-setCapacity:] + * doesn't clear newly allocated bytes + * sets the size of the allocated buffer. + * + * The actual class hierarchy is as follows - + * + * NSData Abstract base class. + * NSDataMalloc Concrete class. + * NSDataMappedFile Memory mapped files. + * NSDataShared Extension for shared memory. + * NSDataStatic Extension for static buffers. + * NSMutableData Abstract base class. + * NSMutableDataMalloc Concrete class. + * NSMutableDataShared Extension for shared memory. + * + * Since all the other subclasses are based on NSDataMalloc or + * NSMutableDataMalloc, we can put most methods in here and not + * bother with duplicating them in the other classes. + * + */ + #include #include #include +#include #include #include #include #include #include +#include #include /* for memset() */ #include /* SEEK_* on SunOS 4 */ -/* xxx Pretty messy. Needs work. */ - -@implementation NSData - -static Class NSData_concrete_class; -static Class NSMutableData_concrete_class; - -+ (void) _setConcreteClass: (Class)c -{ - NSData_concrete_class = c; -} - -+ (void) _setMutableConcreteClass: (Class)c -{ - NSMutableData_concrete_class = c; -} - -+ (Class) _concreteClass -{ - return NSData_concrete_class; -} - -+ (Class) _mutableConcreteClass -{ - return NSMutableData_concrete_class; -} - -+ (void) initialize -{ -#if 0 - NSData_concrete_class = [NSGData class]; - NSMutableData_concrete_class = [NSGMutableData class]; -#else - NSData_concrete_class = [NSHData class]; - NSMutableData_concrete_class = [NSHMutableData class]; +#if HAVE_MMAP +#include +#include +#include +#ifndef MAP_FAILED +#define MAP_FAILED ((void*)-1) /* Failure address. */ +#endif +@class NSDataMappedFile; #endif -} -// Allocating and Initializing a Data Object -+ allocWithZone:(NSZone *)zone -{ - return NSAllocateObject([self _concreteClass], 0, zone); -} +#if HAVE_SHMCTL +#include +#include -+ (id) data -{ - return [[[self alloc] init] - autorelease]; -} +#define VM_ACCESS 0644 /* self read/write - other readonly */ +@class NSDataShared; +@class NSMutableDataShared; +#endif -+ (id) dataWithBytes: (const void*)bytes - length: (unsigned int)length -{ - return [[[self alloc] initWithBytes:bytes length:length] - autorelease]; -} +@class NSDataMalloc; +@class NSDataStatic; +@class NSMutableDataMalloc; -+ (id) dataWithBytesNoCopy: (void*)bytes - length: (unsigned int)length -{ - return [[[self alloc] initWithBytesNoCopy:bytes length:length] - autorelease]; -} -/* FIXME: Should these next two be autorelease? The pattern says yes. - * But the docs fail to explicitly indicate it. It only makes sense, - * though. */ -+ (id)dataWithContentsOfFile: (NSString*)path +static BOOL +readContentsOfFile(NSString* path, void** buf, unsigned* len) { - return [[[self alloc] initWithContentsOfFile:path] - autorelease]; -} - -+ (id) dataWithContentsOfMappedFile: (NSString*)path -{ - return [[[self alloc] initWithContentsOfMappedFile:path] - autorelease]; -} - -- (id) initWithBytes: (const void*)bytes - length: (unsigned int)length -{ - /* xxx Eventually we'll have to be aware of malloc'ed memory - vs vm_allocate'd memory, etc. */ - void *buf = NSZoneMalloc([self zone], length); - memcpy(buf, bytes, length); - return [self initWithBytesNoCopy:buf length:length]; -} - -/* This is the (internal) designated initializer for NSData. This routine - should only be called by known subclasses of NSData. Other subclasses - should just use [super init]. */ -- (id) _initWithBytesNoCopy: (void*)bytes - length: (unsigned int)length -{ - return [super init]; -} - -- (id) initWithBytesNoCopy: (void*)bytes - length: (unsigned int)length -{ - /* xxx Eventually we'll have to be aware of malloc'ed memory - vs vm_allocate'd memory, etc. */ - [self subclassResponsibility:_cmd]; - return nil; -} - -- init -{ - /* xxx Is this right? */ - /* FIXME: It seems so; mutable subclasses need to deal gracefully - * with NULL pointers and/or 0 length data objects, though. Which - * they do. */ - return [self _initWithBytesNoCopy:NULL length:0]; -} - -- (id) initWithContentsOfFile: (NSString *)path -{ - void *tmpBytes; - const char *theFileName; - FILE *theFile; - long int length; - long int d; - int c; - - /* FIXME: I'm not sure that I'm dealing with failures correctly - * here. I just return nil; should I return something like - * - * [self initWithBytesNoCopy:NULL length:0] - * - * instead? The docs don't indicate any exception raising should - * take place; so what else can I do? */ + const char *theFileName; + FILE *theFile = 0; + unsigned int fileLength; + void *tmp = 0; + int c; /* FIXME: I believe that we should take the name of the file to be * the cString of the path provided. It is unclear, however, that @@ -172,68 +109,177 @@ static Class NSMutableData_concrete_class; * bidirectional, this simple translation might not be the proper * one. */ - theFileName = [path cString]; + theFileName = [path cStringNoCopy]; theFile = fopen(theFileName, "r"); - + if (theFile == NULL) /* We failed to open the file. */ - goto failure; + { + NSLog(@"Open (%s) attempt failed - %s", theFileName, strerror(errno)); + goto failure; + } /* Seek to the end of the file. */ c = fseek(theFile, 0L, SEEK_END); - - if (c != 0) /* Something went wrong; though I - * don't know what. */ - goto failure; + if (c != 0) + { + NSLog(@"Seek to end of file failed - %s", strerror(errno)); + goto failure; + } /* Determine the length of the file (having seeked to the end of the * file) by calling ftell(). */ - length = ftell(theFile); - - if (length == -1) /* I can't imagine what could go - * wrong, but here we are. */ - goto failure; + fileLength = ftell(theFile); + if (fileLength == -1) + { + NSLog(@"Ftell failed - %s", strerror(errno)); + goto failure; + } - /* Set aside the space we'll need. */ - tmpBytes = NSZoneMalloc([self zone], length); - - if (tmpBytes == NULL) /* Out of memory, I guess. */ - goto failure; + tmp = malloc(fileLength); + if (tmp == 0) + { + NSLog(@"Malloc failed for file of length %d- %s", + fileLength, strerror(errno)); + goto failure; + } /* Rewind the file pointer to the beginning, preparing to read in * the file. */ c = fseek(theFile, 0L, SEEK_SET); - - if (c != 0) /* Oh, No. */ - goto failure; + if (c != 0) + { + NSLog(@"Fseek to start of file failed - %s", strerror(errno)); + goto failure; + } - /* Now we read the file into tmpBytes one (unsigned) byte at a - * time. We should probably be more careful to check that we don't - * get an EOF. But what would this mean? That the file had been - * changed in the middle of all this. So maybe we should think - * about locking the file? */ - for (d = 0; d < length; d++) - ((unsigned char *)tmpBytes)[d] = (unsigned char) fgetc(theFile); + c = fread(tmp, 1, fileLength, theFile); + if (c != fileLength) + { + NSLog(@"Fread of file contents failed - %s", strerror(errno)); + goto failure; + } - /* success: */ - return [self initWithBytesNoCopy:tmpBytes length:length]; + *buf = tmp; + *len = fileLength; + return YES; /* Just in case the failure action needs to be changed. */ failure: + if (tmp) + free(tmp); + if (theFile) + fclose(theFile); + return NO; +} + + +@interface NSDataMalloc : NSData +{ + unsigned int length; + void *bytes; +} +@end + +@interface NSMutableDataMalloc : NSMutableData +{ + unsigned int capacity; + unsigned int length; + void *bytes; +} +@end + +#if HAVE_MMAP +@interface NSDataMappedFile : NSDataMalloc +@end +#endif + +#if HAVE_SHMCTL +@interface NSDataShared : NSDataMalloc +{ + int shmid; +} +- (id) initWithShmID: (int)anId length: (unsigned)bufferSize; +@end + +@interface NSMutableDataShared : NSMutableDataMalloc +{ + int shmid; +} +- (id) initWithShmID: (int)anId length: (unsigned)bufferSize; +@end +#endif + +@interface NSDataStatic: NSDataMalloc +@end + + +@implementation NSData ++ (NSData*) allocWithZone: (NSZone*)z +{ + return (NSData*)NSAllocateObject([NSDataMalloc class], 0, z); +} + ++ (id) data +{ + return [[[NSDataStatic alloc] initWithBytesNoCopy: 0 length: 0] + autorelease]; +} + ++ (id) dataWithBytes: (const void*)bytes + length: (unsigned int)length +{ + return [[[NSDataMalloc alloc] initWithBytes:bytes length:length] + autorelease]; +} + ++ (id) dataWithBytesNoCopy: (void*)bytes + length: (unsigned int)length +{ + return [[[NSDataMalloc alloc] initWithBytesNoCopy:bytes length:length] + autorelease]; +} + ++ (id) dataWithContentsOfFile: (NSString*)path +{ + return [[[NSDataMalloc alloc] initWithContentsOfFile:path] + autorelease]; +} + ++ (id) dataWithContentsOfMappedFile: (NSString*)path +{ +#if HAVE_MMAP + return [[[NSDataMappedFile alloc] initWithContentsOfMappedFile:path] + autorelease]; +#else + return [[[NSDataMalloc alloc] initWithContentsOfMappedFile:path] + autorelease]; +#endif +} + +- (id) initWithBytes: (const void*)bytes + length: (unsigned int)length +{ + [self subclassResponsibility:_cmd]; + return nil; +} + +- (id) initWithBytesNoCopy: (void*)bytes + length: (unsigned int)length +{ + [self subclassResponsibility:_cmd]; + return nil; +} + +- (id) initWithContentsOfFile: (NSString *)path +{ + [self subclassResponsibility:_cmd]; return nil; } - (id) initWithContentsOfMappedFile: (NSString *)path; { - /* FIXME: Until I can learn about mapped files on various systems, - * the docs indicate that this should be identical with - * - * [self initWithContentsOfFile:path]. - * - * Linux, for example, has mapped files, as do many (all?) SYSV - * unices, but I don't know enough about these various systems to - * deal with them. Does any POSIX standard specify mapped file - * capabilities? */ - return [self initWithContentsOfFile:path]; + [self subclassResponsibility:_cmd]; + return nil; } - (id) initWithData: (NSData*)data @@ -252,15 +298,19 @@ static Class NSMutableData_concrete_class; - (NSString*) description { - const char *src = [self bytes]; - char *dest; - int length = [self length]; - int i,j; + NSString *str; + const char *src = [self bytes]; + char *dest; + int length = [self length]; + int i,j; #define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57)) /* we can just build a cString and convert it to an NSString */ - dest = (char*) malloc (2*length+length/4+3); + dest = (char*) objc_malloc (2*length+length/4+3); + if (dest == 0) + [NSException raise:NSMallocException + format:@"No memory for description of NSData object"]; dest[0] = '<'; for (i=0,j=1; i= size || NSMaxRange( aRange ) > size) { - /* FIXME: I think that this is the proper way to raise this - * exception. Maybe not, though. Does GNUStep have a standard - * format that ``internal'' exceptions like this one should have? - * If not, then maybe it should. It would help debugging. */ - - /* Raise an exception. - * I, too, do not know if GNUStep has a standard - * format. I do feel, however, that more info is - * better. Note that the previous check did not - * check both ends of the range. - */ - [NSException raise : NSRangeException - format : @"Range: (%u, %u) Size: %d", - aRange.location, - aRange.length, - size]; + [NSException raise: NSRangeException + format: @"Range: (%u, %u) Size: %d", + aRange.location, aRange.length, size]; } else - /* FIXME: I guess we're guaranteed that memcpy() exists? */ memcpy(buffer, [self bytes] + aRange.location, aRange.length); return; } - (NSData*) subdataWithRange: (NSRange)aRange { - void *buffer; + void *buffer; + unsigned l = [self length]; - /* FIXME: Just a question; is it safe to have all of the - * NSZoneMalloc'ing without closing NSZoneFree'ing? It seems to be - * popular in this code. */ - buffer = NSZoneMalloc([self zone], aRange.length); + // Check for 'out of range' errors before calling [-getBytes:range:] + // so that we can be sure that we don't get a range exception raised + // after we have allocated memory. + l = [self length]; + if (aRange.location >= l || aRange.length >= l || NSMaxRange(aRange) > l) + [NSException raise: NSRangeException + format: @"Range: (%u, %u) Size: %d", + aRange.location, aRange.length, l]; - /* Remember, [NSData -getBytes:range:] will raise an exception if - * aRange is out-of-bounds. */ + buffer = malloc(aRange.length); + if (buffer == 0) + [NSException raise:NSMallocException + format:@"No memory for subdata of NSData object"]; [self getBytes:buffer range:aRange]; - /* FIXME: Should this be an autoreleased object, as it is now? */ return [NSData dataWithBytesNoCopy:buffer length:aRange.length]; } +- (unsigned int) hash +{ + return [self length]; +} + - (BOOL) isEqual: anObject { - /* FIXME: OpenStep uses -isKindOfClass: rather than -isKindOf:. Is - * it better to use -isKindOf:, since we know we're using GNUObjC? - * It seems to me more prudent to stick with the OpenStep version, - * since we're writing OpenStep code. */ - if ([anObject isKindOf:[NSData class]]) + if ([anObject isKindOfClass:[NSData class]]) return [self isEqualToData:anObject]; return NO; } @@ -372,7 +417,7 @@ static Class NSMutableData_concrete_class; // Storing Data - (BOOL) writeToFile: (NSString *)path - atomically: (BOOL)useAuxiliaryFile + atomically: (BOOL)useAuxiliaryFile { const char *theFileName; const char *theRealFileName = NULL; @@ -412,7 +457,10 @@ static Class NSMutableData_concrete_class; if (theFile == NULL) /* Something went wrong; we weren't * even able to open the file. */ - goto failure; + { + NSLog(@"Open (%s) failed - %s", theFileName, strerror(errno)); + goto failure; + } /* Now we try and write the NSData's bytes to the file. Here `c' is * the number of bytes which were successfully written to the file @@ -424,7 +472,10 @@ static Class NSMutableData_concrete_class; if (c < [self length]) /* We failed to write everything for * some reason. */ - goto failure; + { + NSLog(@"Fwrite (%s) failed - %s", theFileName, strerror(errno)); + goto failure; + } /* We're done, so close everything up. */ c = fclose(theFile); @@ -432,7 +483,10 @@ static Class NSMutableData_concrete_class; if (c != 0) /* I can't imagine what went wrong * closing the file, but we got here, * so we need to deal with it. */ - goto failure; + { + NSLog(@"Fclose (%s) failed - %s", theFileName, strerror(errno)); + goto failure; + } /* If we used a temporary file, we still need to rename() it be the * real file. Am I forgetting anything here? */ @@ -442,7 +496,10 @@ static Class NSMutableData_concrete_class; if (c != 0) /* Many things could go wrong, I * guess. */ - goto failure; + { + NSLog(@"Rename (%s) failed - %s", theFileName, strerror(errno)); + goto failure; + } } /* success: */ @@ -453,7 +510,7 @@ static Class NSMutableData_concrete_class; return NO; } - + // Deserializing Data - (unsigned int)deserializeAlignedBytesLengthAtCursor:(unsigned int*)cursor @@ -462,8 +519,8 @@ static Class NSMutableData_concrete_class; } - (void)deserializeBytes:(void*)buffer - length:(unsigned int)bytes - atCursor:(unsigned int*)cursor + length:(unsigned int)bytes + atCursor:(unsigned int*)cursor { NSRange range = { *cursor, bytes }; [self getBytes:buffer range:range]; @@ -471,9 +528,9 @@ static Class NSMutableData_concrete_class; } - (void)deserializeDataAt:(void*)data - ofObjCType:(const char*)type - atCursor:(unsigned int*)cursor - context:(id )callback + ofObjCType:(const char*)type + atCursor:(unsigned int*)cursor + context:(id )callback { if(!type || !data) return; @@ -635,8 +692,8 @@ static Class NSMutableData_concrete_class; } - (void)deserializeInts:(int*)intBuffer - count:(unsigned int)numInts - atCursor:(unsigned int*)cursor + count:(unsigned int)numInts + atCursor:(unsigned int*)cursor { unsigned i; @@ -648,8 +705,8 @@ static Class NSMutableData_concrete_class; } - (void)deserializeInts:(int*)intBuffer - count:(unsigned int)numInts - atIndex:(unsigned int)index + count:(unsigned int)numInts + atIndex:(unsigned int)index { unsigned i; @@ -672,57 +729,108 @@ static Class NSMutableData_concrete_class; return nil; } +- (void) encodeWithCoder:(NSCoder*)coder +{ + [self subclassResponsibility:_cmd]; +} + +- (id) initWithCoder:(NSCoder*)coder +{ + [self subclassResponsibility:_cmd]; + return nil; +} + @end - -/* xxx Pretty messy. Needs work. */ - -@implementation NSMutableData - -+ allocWithZone:(NSZone *)zone +@implementation NSData (GNUstepExtensions) ++ (id) dataWithShmID: (int)anID length: (unsigned)length { - return NSAllocateObject([self _mutableConcreteClass], 0, zone); +#if HAVE_SHMCTL + return [[[NSDataShared alloc] initWithShmID:anID length:length] + autorelease]; +#else + NSLog(@"[NSData -dataWithSmdID:length:] no shared memory support"); + return nil; +#endif +} + ++ (id) dataWithSharedBytes: (const void*)bytes length: (unsigned)length +{ +#if HAVE_SHMCTL + return [[[NSDataShared alloc] initWithBytes:bytes length:length] + autorelease]; +#else + return [[[NSDataMalloc alloc] initWithBytes:bytes length:length] +#endif +} + ++ (id) dataWithStaticBytes: (const void*)bytes length: (unsigned)length +{ + return [[[NSDataStatic alloc] initWithBytesNoCopy:(void*)bytes length:length] + autorelease]; +} +@end + + +@implementation NSMutableData ++ (NSData*) allocWithZone: (NSZone*)z +{ + return (NSData*)NSAllocateObject([NSMutableDataMalloc class], 0, z); +} + ++ (id) dataWithBytes: (const void*)bytes + length: (unsigned int)length +{ + return [[[NSMutableDataMalloc alloc] initWithBytes:bytes length:length] + autorelease]; +} + ++ (id) dataWithBytesNoCopy: (void*)bytes + length: (unsigned int)length +{ + return [[[NSMutableDataMalloc alloc] initWithBytesNoCopy:bytes length:length] + autorelease]; } + (id) dataWithCapacity: (unsigned int)numBytes { - return [[[self alloc] initWithCapacity:numBytes] + return [[[NSMutableDataMalloc alloc] initWithCapacity:numBytes] + autorelease]; +} + ++ (id) dataWithContentsOfFile: (NSString*)path +{ + return [[[NSMutableDataMalloc alloc] initWithContentsOfFile:path] + autorelease]; +} + ++ (id) dataWithContentsOfMappedFile: (NSString*)path +{ + return [[[NSMutableDataMalloc alloc] initWithContentsOfFile:path] autorelease]; } + (id) dataWithLength: (unsigned int)length { - return [[[self alloc] initWithLength:length] + return [[[NSMutableDataMalloc alloc] initWithLength:length] autorelease]; } +- (const void*) bytes +{ + return [self mutableBytes]; +} + - (id) initWithCapacity: (unsigned int)capacity { - return [self initWithBytesNoCopy: objc_malloc (capacity) - length:capacity]; -} - -- (id) initWithBytesNoCopy: (void*)bytes - length: (unsigned int)length -{ - /* xxx Eventually we'll have to be aware of malloc'ed memory - vs vm_allocate'd memory, etc. */ [self subclassResponsibility:_cmd]; return nil; } - (id) initWithLength: (unsigned int)length { - [self initWithCapacity:length]; - memset ((char*)[self bytes], 0, length); - return self; -} - -/* This method not in OpenStep */ -- (unsigned) capacity -{ - [self subclassResponsibility: _cmd]; - return 0; + [self subclassResponsibility:_cmd]; + return nil; } // Adjusting Capacity @@ -732,7 +840,7 @@ static Class NSMutableData_concrete_class; [self setLength:[self length]+extraLength]; } -- (void) setLength: (unsigned int)length +- (void) setLength: (unsigned)size { [self subclassResponsibility:_cmd]; } @@ -745,16 +853,21 @@ static Class NSMutableData_concrete_class; // Appending Data -- (void) appendBytes: (const void*)bytes - length: (unsigned int)length +- (void) appendBytes: (const void*)aBuffer + length: (unsigned int)bufferSize { - [self subclassResponsibility:_cmd]; + unsigned oldLength = [self length]; + void* buffer; + + [self setLength: oldLength + bufferSize]; + buffer = [self mutableBytes]; + memcpy(buffer + oldLength, aBuffer, bufferSize); } - (void) appendData: (NSData*)other { [self appendBytes:[other bytes] - length:[other length]]; + length:[other length]]; } @@ -951,3 +1064,746 @@ static Class NSMutableData_concrete_class; @end +@implementation NSMutableData (GNUstepExtensions) ++ (id) dataWithShmID: (int)anID length: (unsigned)length +{ +#if HAVE_SHMCTL + return [[[NSMutableDataShared alloc] initWithShmID:anID length:length] + autorelease]; +#else + NSLog(@"[NSMutableData -dataWithSmdID:length:] no shared memory support"); + return nil; +#endif +} + ++ (id) dataWithSharedBytes: (const void*)bytes length: (unsigned)length +{ +#if HAVE_SHMCTL + return [[[NSMutableDataShared alloc] initWithBytes:bytes length:length] + autorelease]; +#else + return [[[NSMutableDataMalloc alloc] initWithBytes:bytes length:length] + autorelease]; +#endif +} + +- (unsigned int) capacity +{ + [self subclassResponsibility: _cmd]; + return 0; +} + +- (id) setCapacity: (unsigned int)newCapacity +{ + [self subclassResponsibility: _cmd]; + return nil; +} + +- (int) shmID +{ + return -1; +} +@end + + +@implementation NSDataMalloc ++ (NSData*) allocWithZone: (NSZone*)z +{ + return (NSData*)NSAllocateObject([NSDataMalloc class], 0, z); +} + +- (const void*) bytes +{ + return bytes; +} + +- (Class) classForArchiver +{ + return [NSDataMalloc class]; +} + +- (Class) classForCoder +{ + return [NSDataMalloc class]; +} + +- (Class) classForPortCoder +{ + return [NSDataMalloc class]; +} + +- (id) copyWithZone: (NSZone*)zone +{ + return [self retain]; +} + +- (void) dealloc +{ + if (bytes) + { + free(bytes); + bytes = 0; + length = 0; + } + [super dealloc]; +} + +- (void) encodeWithCoder: (NSCoder*)aCoder +{ + [aCoder encodeValueOfObjCType:"I" at: &length]; + [aCoder encodeArrayOfObjCType:"C" count:length at: bytes]; +} + +- (id) init +{ + return [self initWithBytesNoCopy: 0 length: 0]; +} + +- (id) initWithBytes: (const void*)aBuffer length: (unsigned int)bufferSize +{ + void* tmp = 0; + + if (aBuffer != 0 && bufferSize > 0) + { + tmp = malloc(bufferSize); + if (tmp == 0) + { + NSLog(@"[NSDataMalloc -initWithBytes:length:] unable to allocate %lu bytes", bufferSize); + [self dealloc]; + return nil; + } + else + { + memcpy(tmp, aBuffer, bufferSize); + } + } + self = [self initWithBytesNoCopy:tmp length:bufferSize]; + return self; +} + +- (id) initWithBytesNoCopy: (void*)aBuffer + length: (unsigned int)bufferSize +{ + self = [super init]; + if (self) + { + bytes = aBuffer; + if (bytes) + length = bufferSize; + } + else + if (aBuffer) + free(aBuffer); + return self; +} + +- (id) initWithCoder: (NSCoder*)aCoder +{ + unsigned int l; + void* b; + + [aCoder decodeValueOfObjCType:"I" at: &l]; + b = malloc(l); + [aCoder decodeArrayOfObjCType:"C" count: l at: b]; + return [self initWithBytesNoCopy: b length: l]; +} + +- (id) initWithContentsOfFile: (NSString *)path +{ + self = [super init]; + if (readContentsOfFile(path, &bytes, &length) == NO) + { + [self dealloc]; + self = nil; + } + return self; +} + +- (id) initWithContentsOfMappedFile: (NSString *)path +{ +#if HAVE_MMAP + [self dealloc]; + self = [NSDataMappedFile alloc]; + return [self initWithContentsOfMappedFile:path]; +#else + return [self initWithContentsOfFile:path]; +#endif +} + +- (id) initWithData: (NSData*)anObject +{ + if (anObject == nil) + return [self initWithBytesNoCopy: 0 length: 0]; + + if ([anObject isKindOfClass:[NSData class]] == NO) + { + [self dealloc]; + return nil; + } + if ([anObject isKindOfClass:[NSMutableData class]] == NO) + { + [self dealloc]; + return [anObject retain]; + } + else + return [self initWithBytes: [anObject bytes] length: [anObject length]]; +} + +- (unsigned int) length +{ + return length; +} + +- (id) mutableCopyWithZone: (NSZone*)zone +{ + return [[NSMutableDataMalloc allocWithZone:zone] initWithBytes: bytes + length: length]; +} + +@end + +#if HAVE_MMAP +@implementation NSDataMappedFile ++ (NSData*) allocWithZone: (NSZone*)z +{ + return (NSData*)NSAllocateObject([NSDataMappedFile class], 0, z); +} + +- (void) dealloc +{ + if (bytes) + { + munmap(bytes, length); + bytes = 0; + length = 0; + } + [super dealloc]; +} + +- (id) initWithContentsOfMappedFile: (NSString*)path +{ + int fd; + const char *theFileName = [path cStringNoCopy]; + + fd = open(theFileName, O_RDONLY); + if (fd < 0) + { + NSLog(@"[NSDataMappedFile -initWithContentsOfMappedFile:] unable to open %s - %s", theFileName, strerror(errno)); + [self dealloc]; + return nil; + } + /* Find size of file to be mapped. */ + length = lseek(fd, 0, SEEK_END); + if (length < 0) + { + NSLog(@"[NSDataMappedFile -initWithContentsOfMappedFile:] unable to seek to eof %s - %s", theFileName, strerror(errno)); + close(fd); + [self dealloc]; + return nil; + } + /* Position at start of file. */ + if (lseek(fd, 0, SEEK_SET) != 0) + { + NSLog(@"[NSDataMappedFile -initWithContentsOfMappedFile:] unable to seek to sof %s - %s", theFileName, strerror(errno)); + close(fd); + [self dealloc]; + return nil; + } + bytes = mmap(0, length, PROT_READ, MAP_SHARED, fd, 0); + if (bytes == MAP_FAILED) + { + NSLog(@"[NSDataMappedFile -initWithContentsOfMappedFile:] mapping failed for %s - %s", theFileName, strerror(errno)); + close(fd); + [self dealloc]; + self = [NSDataMalloc alloc]; + self = [self initWithContentsOfFile: path]; + } + close(fd); + return self; +} + +@end +#endif /* HAVE_MMAP */ + +#if HAVE_SHMCTL +@implementation NSDataShared ++ (NSData*) allocWithZone: (NSZone*)z +{ + return (NSData*)NSAllocateObject([NSDataShared class], 0, z); +} + +- (void) dealloc +{ + if (bytes) + { + shmdt(bytes); + bytes = 0; + length = 0; + shmid = -1; + } + [super dealloc]; +} + +- (id) initWithBytes: (const void*)aBuffer length: (unsigned)bufferSize +{ + struct shmid_ds buf; + + self = [super init]; + if (self == nil) + return nil; + shmid = -1; + if (aBuffer && bufferSize) + { + shmid = shmget(IPC_PRIVATE, bufferSize, IPC_CREAT|VM_ACCESS); + if (shmid == -1) /* Created memory? */ + { + NSLog(@"[-initWithBytes:length:] shared mem get failed for %u - %s", + bufferSize, strerror(errno)); + [self dealloc]; + self = [NSDataMalloc alloc]; + return [self initWithBytes: aBuffer length: bufferSize]; + } + + bytes = shmat(shmid, 0, 0); + shmctl(shmid, IPC_RMID, &buf); /* Mark for later deletion. */ + if (bytes == (void*)-1) + { + NSLog(@"[-initWithBytes:length:] shared mem attach failed for %u - %s", + bufferSize, strerror(errno)); + bytes = 0; + [self dealloc]; + self = [NSDataMalloc alloc]; + return [self initWithBytes: aBuffer length: bufferSize]; + } + length = bufferSize; + } + return self; +} + +- (id) initWithShmID: (int)anId length: (unsigned)bufferSize +{ + struct shmid_ds buf; + + self = [super init]; + if (self == nil) + return nil; + + shmid = anId; + if (shmctl(shmid, IPC_STAT, &buf) < 0) + { + NSLog(@"[NSDataShared -initWithShmID:length:] shared memory control failed - %s", strerror(errno)); + [self dealloc]; /* Unable to access memory. */ + return nil; + } + if (buf.shm_segsz < bufferSize) + { + NSLog(@"[NSDataShared -initWithShmID:length:] shared memory segment too small"); + [self dealloc]; /* Memory segment too small. */ + return nil; + } + bytes = shmat(shmid, 0, 0); + if (bytes == (void*)-1) + { + NSLog(@"[NSDataShared -initWithShmID:length:] shared memory attach failed - %s", + strerror(errno)); + bytes = 0; + [self dealloc]; /* Unable to attach to memory. */ + return nil; + } + length = bufferSize; + return self; +} + +- (int) shmID +{ + return shmid; +} + +@end +#endif /* HAVE_SHMCTL */ + + +@implementation NSDataStatic ++ (NSData*) allocWithZone: (NSZone*)z +{ + return (NSData*)NSAllocateObject([NSDataStatic class], 0, z); +} + +- (void) dealloc +{ + bytes = 0; + length = 0; + [super dealloc]; +} + +- (id) init +{ + return [self initWithBytesNoCopy: 0 length: 0]; +} + +- (id) initWithBytesNoCopy: (void*)aBuffer + length: (unsigned int)bufferSize +{ + self = [super init]; + if (self) + { + bytes = aBuffer; + if (bytes) + length = bufferSize; + } + return self; +} + +@end + +@implementation NSMutableDataMalloc ++ (NSData*) allocWithZone: (NSZone*)z +{ + return (NSData*)NSAllocateObject([NSMutableDataMalloc class], 0, z); +} + +- (unsigned int) capacity +{ + return capacity; +} + +- (Class) classForArchiver +{ + return [NSMutableDataMalloc class]; +} + +- (Class) classForCoder +{ + return [NSMutableDataMalloc class]; +} + +- (Class) classForPortCoder +{ + return [NSMutableDataMalloc class]; +} + +- (id) copyWithZone: (NSZone*)zone +{ + return [[NSDataMalloc allocWithZone:zone] initWithBytes:bytes length:length]; +} + +- (void) dealloc +{ + if (bytes) + { + free(bytes); + bytes = 0; + length = 0; + capacity = 0; + } + [super dealloc]; +} + +- (void) encodeWithCoder: (NSCoder*)aCoder +{ + [aCoder encodeValueOfObjCType:"I" at: &length]; + [aCoder encodeArrayOfObjCType:"C" count:length at: bytes]; +} + +- (id) init +{ + return [self initWithBytesNoCopy: 0 length: 0]; +} + +- (id) initWithBytes: (const void*)aBuffer length: (unsigned int)bufferSize +{ + self = [self initWithCapacity: bufferSize]; + if (self) + { + if (aBuffer && bufferSize > 0) + { + memcpy(bytes, aBuffer, bufferSize); + length = bufferSize; + } + } + return self; +} + +- (id) initWithBytesNoCopy: (void*)aBuffer + length: (unsigned int)bufferSize +{ + self = [self initWithCapacity: 0]; + if (self) + { + bytes = aBuffer; + if (bytes) + { + length = bufferSize; + capacity = bufferSize; + } + } + else + if (aBuffer) + free(aBuffer); + return self; +} + +/* + * THIS IS THE DESIGNATED INITIALISER + */ +- (id) initWithCapacity: (unsigned)size +{ + self = [super init]; + if (self) + { + if (size) + { + bytes = malloc(size); + if (bytes == 0) + { + NSLog(@"[NSMutableDataMalloc -initWithCapacity:] out of memory for %u bytes - %s", size, strerror(errno)); + [self dealloc]; + return nil; + } + } + capacity = size; + length = 0; + } + return self; +} + +- (id) initWithCoder: (NSCoder*)aCoder +{ + unsigned int l; + void* b; + + [aCoder decodeValueOfObjCType:"I" at: &l]; + b = malloc(l); + [aCoder decodeArrayOfObjCType:"C" count: l at: b]; + return [self initWithBytesNoCopy: b length: l]; +} + +- (id) initWithLength: (unsigned)size +{ + self = [self initWithCapacity: size]; + if (self) + { + memset(bytes, '\0', size); + length = size; + } + return self; +} + +- (id) initWithContentsOfFile: (NSString *)path +{ + self = [self initWithCapacity: 0]; + if (readContentsOfFile(path, &bytes, &length) == NO) + { + [self dealloc]; + self = nil; + } + else + capacity = length; + return self; +} + +- (id) initWithContentsOfMappedFile: (NSString *)path +{ + return [self initWithContentsOfFile:path]; +} + +- (id) initWithData: (NSData*)anObject +{ + if (anObject == nil) + return [self initWithBytesNoCopy: 0 length: 0]; + + if ([anObject isKindOfClass:[NSData class]] == NO) + { + [self dealloc]; + return nil; + } + return [self initWithBytes: [anObject bytes] length: [anObject length]]; +} + +- (unsigned int) length +{ + return length; +} + +- (void*) mutableBytes +{ + return bytes; +} + +- (id) mutableCopyWithZone: (NSZone*)zone +{ + return [[NSMutableDataMalloc allocWithZone:zone] initWithBytes: bytes + length: length]; +} + +- (id) setCapacity: (unsigned int)size +{ + if (size != capacity) + { + void* tmp = objc_realloc(bytes, size); + + if (tmp == 0) + [NSException raise:NSMallocException + format:@"Unable to set data capacity to '%d'", size]; + + bytes = tmp; + capacity = size; + } + if (size < length) + length = size; + return self; +} + +- (void) setLength: (unsigned)size +{ + if (size > capacity) + [self setCapacity: size]; + + if (size > length) + memset(bytes + length, '\0', size - length); + + length = size; +} + +@end + + +#if HAVE_SHMCTL +@implementation NSMutableDataShared ++ (NSData*) allocWithZone: (NSZone*)z +{ + return (NSData*)NSAllocateObject([NSMutableDataShared class], 0, z); +} + +- (void) dealloc +{ + if (bytes) + { + shmdt(bytes); + bytes = 0; + length = 0; + capacity = 0; + shmid = -1; + } + [super dealloc]; +} + +- (id) initWithBytes: (const void*)aBuffer length: (unsigned)bufferSize +{ + self = [self initWithCapacity: bufferSize]; + if (self) + { + if (bufferSize && aBuffer) + memcpy(bytes, aBuffer, bufferSize); + length = bufferSize; + } + return self; +} + +- (id) initWithCapacity: (unsigned)bufferSize +{ + struct shmid_ds buf; + int e; + + self = [super initWithCapacity: 0]; + if (self) + { + shmid = shmget(IPC_PRIVATE, bufferSize, IPC_CREAT|VM_ACCESS); + if (shmid == -1) /* Created memory? */ + { + NSLog(@"[NSMutableDataShared -initWithCapacity:] shared memory get failed for %u - %s", bufferSize, strerror(errno)); + [self dealloc]; + self = [NSMutableDataMalloc alloc]; + return [self initWithCapacity: bufferSize]; + } + + bytes = shmat(shmid, 0, 0); + e = errno; + shmctl(shmid, IPC_RMID, &buf); /* Mark for later deletion. */ + + if (bytes == (void*)-1) + { + NSLog(@"[NSMutableDataShared -initWithCapacity:] shared memory attach failed for %u - %s", bufferSize, strerror(e)); + bytes = 0; + [self dealloc]; + self = [NSMutableDataMalloc alloc]; + return [self initWithCapacity: bufferSize]; + } + length = 0; + capacity = bufferSize; + } + return self; +} + +- (id) initWithShmID: (int)anId length: (unsigned)bufferSize +{ + struct shmid_ds buf; + + self = [super initWithCapacity: 0]; + if (self) + { + shmid = anId; + if (shmctl(shmid, IPC_STAT, &buf) < 0) + { + NSLog(@"[NSMutableDataShared -initWithShmID:length:] shared memory control failed - %s", strerror(errno)); + [self dealloc]; /* Unable to access memory. */ + return nil; + } + if (buf.shm_segsz < bufferSize) + { + NSLog(@"[NSMutableDataShared -initWithShmID:length:] shared memory segment too small"); + [self dealloc]; /* Memory segment too small. */ + return nil; + } + bytes = shmat(shmid, 0, 0); + if (bytes == (void*)-1) + { + NSLog(@"[NSMutableDataShared -initWithShmID:length:] shared memory attach failed - %s", strerror(errno)); + bytes = 0; + [self dealloc]; /* Unable to attach to memory. */ + return nil; + } + length = bufferSize; + capacity = length; + } + return self; +} + +- (id) setCapacity: (unsigned)size +{ + if (size != capacity) + { + void *tmp; + struct shmid_ds buf; + int newid; + + newid = shmget(IPC_PRIVATE, size, IPC_CREAT|VM_ACCESS); + if (newid == -1) /* Created memory? */ + [NSException raise:NSMallocException + format:@"Unable to create shared memory segment - %s.", + strerror(errno)]; + tmp = shmat(newid, 0, 0); + if (shmctl(newid, IPC_RMID, &buf) == 0) /* Mark for later deletion. */ + if ((int)tmp == -1) /* Attached memory? */ + [NSException raise:NSMallocException + format:@"Unable to attach to shared memory segment."]; + memcpy(tmp, bytes, length); + if (bytes) + shmdt(bytes); + bytes = tmp; + shmid = newid; + capacity = size; + } + if (size < length) + length = size; + return self; +} + +- (int) shmID +{ + return shmid; +} + +@end +#endif /* HAVE_SHMCTL */ + diff --git a/Source/NSDate.m b/Source/NSDate.m index 56b638836..89528eb02 100644 --- a/Source/NSDate.m +++ b/Source/NSDate.m @@ -159,7 +159,7 @@ return [self class]; } -- (Class) classForPortCoder: aRmc +- (Class) classForPortCoder { return [self class]; } diff --git a/Source/NSDistantObject.m b/Source/NSDistantObject.m index f5958f5a0..231743127 100644 --- a/Source/NSDistantObject.m +++ b/Source/NSDistantObject.m @@ -570,12 +570,12 @@ format: @"NSDistantObject objects only encode with PortEncoder class"]; argFrame: frame]; } -- classForCoder: (NSCoder*)aCoder; +- classForCoder { return object_get_class (self); } -- classForPortCoder: (NSPortCoder*)aCoder +- classForPortCoder { return object_get_class (self); } @@ -612,15 +612,18 @@ format: @"NSDistantObject objects only encode with PortEncoder class"]; @implementation Protocol (DistributedObjectsCoding) -- (Class) classForPortCoder: (NSPortCoder*)aRmc; +- (Class) classForPortCoder { - return [NSDistantObject class]; + return [self classForCoder]; } - replacementObjectForPortCoder: (NSPortCoder*)aRmc; { - return [NSDistantObject proxyWithLocal: self - connection: [aRmc connection]]; + if ([aRmc isBycopy]) + return self; + else + return [NSDistantObject proxyWithLocal: self + connection: [aRmc connection]]; } @end diff --git a/Source/NSGArchiver.m b/Source/NSGArchiver.m index 1cfd7ef6b..8e291f7b5 100644 --- a/Source/NSGArchiver.m +++ b/Source/NSGArchiver.m @@ -27,6 +27,7 @@ #include #include #include +#include #include #define USE_OPENSTEP_STYLE_FORWARD_REFERENCES 1 @@ -200,20 +201,19 @@ return "NSGUnarchiver"; } -/* if anyone asks for an archivers data we assume that they have finished - archiving and want to read from the data area, so we rewind the stream - and give it to them. Attempting to use the archiver after this will +/* Attempting to use the archiver after this will mess up in a big way. NB. If the archiver was not writing to an NSData object, we can't give one out, so we return nil. */ - (NSMutableData*) archiverData { id s = [cstream stream]; - if ([s isKindOfClass:[NSData class]]) + if ([s isKindOfClass:[MemoryStream class]]) + { + [s rewindStream]; + return [s mutableData]; + } + if ([s isKindOfClass:[NSMutableData class]]) { - if ([s respondsTo:@selector(rewindStream)]) - { - [s rewindStream]; - } return (NSMutableData*)s; } return nil; diff --git a/Source/NSGAttributedString.m b/Source/NSGAttributedString.m index 798989541..6f8d916fd 100644 --- a/Source/NSGAttributedString.m +++ b/Source/NSGAttributedString.m @@ -139,7 +139,7 @@ NSDictionary *_attributesAtIndexEffectiveRange( return nil; } -- (Class) classForPortCoder: (NSPortCoder*)aCoder +- (Class) classForPortCoder { return [self class]; } @@ -203,7 +203,7 @@ NSDictionary *_attributesAtIndexEffectiveRange( @implementation NSGMutableAttributedString -- (Class) classForPortCoder: (NSPortCoder*)aCoder +- (Class) classForPortCoder { return [self class]; } diff --git a/Source/NSGCString.m b/Source/NSGCString.m index e05bb07c9..0cbe5053f 100644 --- a/Source/NSGCString.m +++ b/Source/NSGCString.m @@ -83,7 +83,7 @@ return [self class]; } -- (Class) classForPortCoder: (NSPortCoder*)aCoder +- (Class) classForPortCoder { return [self class]; } diff --git a/Source/NSGData.m b/Source/NSGData.m deleted file mode 100644 index 52c41f53e..000000000 --- a/Source/NSGData.m +++ /dev/null @@ -1,166 +0,0 @@ -/* Concrete NSData for GNUStep based on GNU MemoryStream class - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - - Written by: Andrew Kachites McCallum - Date: April 1995 - - This file is part of the GNUstep Base Library. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - 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 -#include -#include -#include -#include -#include - -/* This from gnustep/base/MemoryStream.h */ -@interface NSGData (MemoryStream) -- _initOnMallocBuffer: (char*)b - size: (unsigned)s /* size of malloc'ed buffer */ - eofPosition: (unsigned)l /* length of buffer with data for reading */ - prefix: (unsigned)p /* reset for this position */ - position: (unsigned)i; /* current position for reading/writing */ -@end - -@implementation NSGData - -+ (void) initialize -{ - static int done = 0; - if (!done) - { - done = 1; - class_add_behavior([NSGData class], [MemoryStream class]); - } -} - -/* This is the (internal) designated initializer */ -- (id) _initWithBytesNoCopy: (void*)bytes - length: (unsigned int)length -{ - /* xxxFIXME: should we call [super _initWithBytesNoCopy:length:]? */ - [self _initOnMallocBuffer:bytes - size:length - eofPosition:length - prefix:0 - position:0]; - return self; -} - -- (id) initWithBytesNoCopy: (void*)bytes - length: (unsigned int)length -{ - return [self _initWithBytesNoCopy:bytes length:length]; -} - -- (const void*) bytes -{ - return buffer; -} - -- (unsigned int) length -{ - return eofPosition; -} - -// Storing Data - -- (BOOL) writeToFile: (NSString*)path - atomically: (BOOL)useAuxiliaryFile -{ - /* xxx This currently ignores useAuxiliaryFile. */ - int written; - FILE* fp = fopen([path cStringNoCopy], "w"); - assert (fp); /* This should raise NSException instead. */ - written = fwrite(buffer+prefix, 1, eofPosition, fp); - assert (eofPosition == written); - fclose(fp); - return YES; -} - -- copyWithZone: (NSZone *)zone -{ - if (NSShouldRetainWithZone(self, zone)) - return [self retain]; - else { - return [[NSData allocWithZone:zone] - initWithBytes:[self bytes] length:[self length]]; - } -} - -- mutableCopyWithZone: (NSZone *)zone -{ - return [[NSMutableData allocWithZone:zone] - initWithBytes:[self bytes] length:[self length]]; -} - -@end - - -@implementation NSGMutableData - -+ (void) initialize -{ - static int done = 0; - if (!done) - { - done = 1; - class_add_behavior([NSGMutableData class], [NSGData class]); - } -} - -/* Make sure we do this, and not what MemoryStream says. */ -- (id) initWithCapacity: (unsigned int)capacity -{ - return [self initWithBytesNoCopy: objc_malloc (capacity) - length:capacity]; -} - -/* This is the designated initializer. The behavior comes from NSGData. - - (id) initWithBytesNoCopy: (void*)bytes - length: (unsigned int)length */ - -- (unsigned) capacity -{ - return size; -} - -- (void) setLength: (unsigned int)length -{ - [self setStreamBufferCapacity:length]; - eofPosition = size; -} - -- (void*) mutableBytes -{ - return buffer; -} - -- (void) appendBytes: (const void*)bytes - length: (unsigned int)length -{ - [self writeBytes:bytes length:length]; -} - -- copyWithZone: (NSZone *)zone -{ - return [[NSData allocWithZone:zone] - initWithBytes:[self bytes] length:[self length]]; -} - -@end diff --git a/Source/NSGString.m b/Source/NSGString.m index 556ea9633..ce4b1bcf3 100644 --- a/Source/NSGString.m +++ b/Source/NSGString.m @@ -225,7 +225,7 @@ return [self class]; } -- (Class) classForPortCoder: (NSPortCoder*)aCoder +- (Class) classForPortCoder { return [self class]; } diff --git a/Source/NSHData.m b/Source/NSHData.m deleted file mode 100644 index c3a26b17a..000000000 --- a/Source/NSHData.m +++ /dev/null @@ -1,1684 +0,0 @@ - -/* Implementation of concrete version of NSData class - Copyright (C) 1997 Free Software Foundation, Inc. - - Written by: Richard Frith-Macdonald - Created: July 1997 - - This file is part of the GNUstep Base Library. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Deal with memchr: */ -#if STDC_HEADERS || HAVE_STRING_H -#include -/* An ANSI string.h and pre-ANSI memory.h might conflict. */ -#if !STDC_HEADERS && HAVE_MEMORY_H -#include -#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ -#define rindex strrchr -#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 -/* memory.h and strings.h conflict on some systems. */ -#endif /* not STDC_HEADERS and not HAVE_STRING_H */ - - - -#if HAVE_MMAP -#define MAPPED_SUPP 1 -#else -#define MAPPED_SUPP 0 -#endif - -#if HAVE_SHMCTL -#define SHARED_SUPP 1 -#else -#define SHARED_SUPP 0 -#endif - -#if MAPPED_SUPP -#include -#include -#include -#ifndef MAP_FAILED -#define MAP_FAILED ((void*)-1) /* Failure address. */ -#endif -#endif - -#if SHARED_SUPP -#include -#include - -#define VM_ACCESS 0644 /* self read/write - other readonly */ -#endif - - - - -extern int -o_vscanf (void *stream, - int (*inchar_func)(void*), - void (*unchar_func)(void*,int), - const char *format, va_list argptr); - -@implementation NSHData - -/* - * OPENSTEP says that if an NSData object is more than a few memory - * pages in size, the memory is allocated from the virtual memory - * system. - * - * I assume that this means something like the system-V shared memory - * mechanism should be used. - * This has the potential to transfer huge buffers from one process to - * another instantly (as you want for pasteboard use etc). - * - * You can set the threshold above which shared memory is used with - * the class method '+setVMThreshold:' which changes the value in - * the 'nsdata_vm_threshold' variable. - * - * Each instance of an NSHMutableData object has its own threshold which - * is set from nsdata_vm_threshold when the object is created. - * This can be modified by using the [-setVMThreshold:] method. - * - * Shared memory is allocated in LARGE chunks. This size can be adjusted - * using the [+setVMChunk:] method. - */ -static int nsdata_vm_threshold = 2048; /* Use shared mem for big buffer. */ -static int nsdata_vm_chunk = 262144; - -/* Making these nested functions (which is what I'd like to do) is - crashing the va_arg stuff in vscanf(). Why? */ -#define DS ((NSHData*)s) - -/* -static int outchar_func(void *s, int c) -{ - if (DS->position >= DS->size) - return EOF; - DS->buffer[DS->position++] = (char)c; - return 1; -} -*/ - -static int inchar_func(void *s) -{ - if (DS->position >= DS->size) - return EOF; - return (int) DS->buffer[DS->position++]; -} - -static void unchar_func(void *s, int c) -{ - if (DS->position > 0) - DS->position--; - DS->buffer[DS->position] = (char)c; -} - -+ allocWithZone:(NSZone *)zone -{ - return NSAllocateObject([NSHData class], 0, zone); -} - -+ (id) data -{ - return [[[self alloc] init] autorelease]; -} - -+ (id) dataWithBytes: (const void*)bytes - length: (unsigned int)length -{ - return [[[self alloc] initWithBytes:bytes length:length] autorelease]; -} - -+ (id) dataWithBytesNoCopy: (void*)bytes - length: (unsigned int)length -{ - return [[[self alloc] initWithBytesNoCopy:bytes length:length] autorelease]; -} - -+ (id)dataWithContentsOfFile: (NSString*)path -{ - return [[[self alloc] initWithContentsOfFile:path] autorelease]; -} - -+ (id) dataWithContentsOfMappedFile: (NSString*)path -{ - return [[[self alloc] initWithContentsOfMappedFile:path] autorelease]; -} - -+ (id) dataWithData: (NSData*)other -{ - return [[[self alloc] initWithData:other] autorelease]; -} - -- (const void*)bytes -{ - return (const void*)buffer; -} - -- classForPortCoder: (NSPortCoder*)aCoder -{ - return object_get_class (self); -} - -- (id) copyWithZone: (NSZone*)zone -{ - NSHData* obj = [[NSHData class] allocWithZone:zone]; - return [obj initWithData:self]; -} - -- (void) dealloc -{ - if (buffer) - { - switch (type) - { -#if MAPPED_SUPP - case MAPPED_DATA: - munmap(buffer, size); - break; - -#endif - case MALLOC_DATA: -#if SHARED_SUPP - case SHARED_DATA: - if (shm_id) /* Was it really malloced data? */ - shmdt(buffer); - else /* Perhaps fall through to free it. */ -#endif - objc_free(buffer); - break; - - case STATIC_DATA: - default: - break; - } - } - [super dealloc]; -} - -- (NSString*) description -{ - const char *src = [self bytes]; - char *dest; - unsigned int length = [self length]; - unsigned int i,j; - NSString *s; - -#define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57)) - - /* we can just build a cString and convert it to an NSString */ - dest = (char*) malloc (2*length+length/4+3); - dest[0] = '<'; - for (i=0,j=1; i>4) & 0x0f); - dest[j] = num2char(src[i] & 0x0f); - if((i&0x3) == 3) - /* if we've just finished a 32-bit int, print a space */ - dest[++j] = ' '; - } - dest[j++] = '>'; - dest[j] = '\0'; - s = [NSString stringWithCString: dest]; - free(dest); - return s; -} - -- (void) encodeWithCoder: (NSCoder*)coder -{ - unsigned int len = [self length]; - - [super encodeWithCoder:coder]; - [coder encodeValuesOfObjCTypes:"I", &len]; - [coder encodeArrayOfObjCType:"C" count:len at:[self bytes]]; -} - -- (void)getBytes: (void*)buf -{ - [self getBytes:buf length:[self length]]; -} - -- (void)getBytes: (void*)bytes - length: (unsigned int)length -{ - [self getBytes:bytes range:((NSRange){0, length})]; -} - -- (void)getBytes: (void*)bytes - range: (NSRange)aRange -{ - if (NSMaxRange(aRange) > [self length]) - [NSException raise:NSRangeException format:@"Out of bounds of Data."]; - else - memcpy(bytes, [self bytes] + aRange.location, aRange.length); - return; -} - -- init -{ - return [self initOnBuffer:0 - size:0 - type:STATIC_DATA - sharedMem:0 - fileName:0 - eofPosition:0 - position:0 - noCopy:NO]; -} - -- (id) initWithBytes: (const void*)bytes - length: (unsigned int)length -{ - /* We initialize with 'noCopy=NO' so that the designated initializer - must take a copy of the data in a malloced buffer */ - return [self initOnBuffer:(void*)bytes - size:length - type:MALLOC_DATA - sharedMem:0 - fileName:0 - eofPosition:length - position:0 - noCopy:NO]; -} - -- (id) initWithBytesNoCopy: (void*)bytes - length: (unsigned int)length -{ - /* We initialize with 'noCopy=YES' so that the designated initializer - can simply adopt the buffer it has been given */ - return [self initOnBuffer:bytes - size:length - type:MALLOC_DATA - sharedMem:0 - fileName:0 - eofPosition:length - position:0 - noCopy:YES]; -} - -- (id) initWithCoder: (NSCoder*)coder -{ - unsigned int len; - - self = [super initWithCoder:coder]; - [coder decodeValuesOfObjCTypes:"I", &len]; - self = [self initOnBuffer:0 - size:len - type:MALLOC_DATA - sharedMem:0 - fileName:0 - eofPosition:0 - position:0 - noCopy:NO]; - [coder decodeArrayOfObjCType:"C" count:len at:buffer]; - eof_position = len; - position = len; - return self; -} - -- (id) initWithContentsOfFile: (NSString *)path -{ - const char *theFileName; - FILE *theFile = 0; - unsigned int length; - int c; - - /* FIXME: I'm not sure that I'm dealing with failures correctly - * here. I just return nil; should I return something like - * - * [self initWithBytesNoCopy:NULL length:0] - * - * instead? The docs don't indicate any exception raising should - * take place; so what else can I do? */ - - /* FIXME: I believe that we should take the name of the file to be - * the cString of the path provided. It is unclear, however, that - * this is correct for fully internationalized functionality. If - * the cString <--> Unicode translation isn't completely - * bidirectional, this simple translation might not be the proper - * one. */ - - theFileName = [path cStringNoCopy]; - theFile = fopen(theFileName, "r"); - - if (theFile == NULL) /* We failed to open the file. */ - goto failure; - - /* Seek to the end of the file. */ - c = fseek(theFile, 0L, SEEK_END); - if (c != 0) - goto failure; - - /* Determine the length of the file (having seeked to the end of the - * file) by calling ftell(). */ - length = ftell(theFile); - if (length == -1) - goto failure; - - self = [self initOnBuffer:0 - size:length - type:MALLOC_DATA - sharedMem:0 - fileName:0 - eofPosition:0 - position:0 - noCopy:NO]; - - if (self == nil) /* Out of memory, I guess. */ - goto failure; - - /* Rewind the file pointer to the beginning, preparing to read in - * the file. */ - c = fseek(theFile, 0L, SEEK_SET); - if (c != 0) /* Oh, No. */ - goto failure; - - c = fread(buffer, 1, length, theFile); - if (c != length) - goto failure; - - /* success: */ - eof_position = length; - return self; - - /* Just in case the failure action needs to be changed. */ - failure: - if (theFile) - fclose(theFile); - if (self) - [self dealloc]; - return nil; -} - -- (id) initWithContentsOfMappedFile: (NSString *)path; -{ -#if MAPPED_SUPP - return [self initOnBuffer:0 - size:0 - type:MAPPED_DATA - sharedMem:0 - fileName:path - eofPosition:0 - position:0 - noCopy:NO]; -#else - return [self initWithContentsOfFile:path]; -#endif -} - -- (id) initWithData: (NSData*)data -{ - return [self initWithBytes:[data bytes] length:[data length]]; -} - -- (BOOL) isEqual: anObject -{ - if ([anObject isKindOfClass:[NSData class]]) - return [self isEqualToData:anObject]; - return NO; -} - -- (BOOL) isEqualToData: (NSData*)other; -{ - unsigned int len; - if ((len = [self length]) != [other length]) - return NO; - return (memcmp([self bytes], [other bytes], len) ? NO : YES); -} - -- (unsigned int)length -{ - return [self streamBufferLength]; -} - -- (id) mutableCopyWithZone: (NSZone*)zone -{ - NSHMutableData* obj = [[NSHMutableData class] allocWithZone:zone]; - return [obj initWithData:self]; -} - -- (id) subdataWithRange: (NSRange)aRange -{ - NSHData* sub = [[NSHData class] allocWithZone:[self zone]]; - - sub = [[sub initOnBuffer:0 - size:aRange.length - type:MALLOC_DATA - sharedMem:0 - fileName:0 - eofPosition:aRange.length - position:0 - noCopy:NO] autorelease]; - if (sub) - [self getBytes:(void*)[sub bytes] range:aRange]; - - return sub; -} - -- (BOOL) writeToFile: (NSString *)path - atomically: (BOOL)useAuxiliaryFile -{ - const char *theFileName; - const char *theRealFileName = NULL; - FILE *theFile; - int c; - - /* FIXME: The docs say nothing about the raising of any exceptions, - * but if someone can provide evidence as to the proper handling of - * bizarre situations here, I'll add whatever functionality is - * needed. For the time being, I'm returning the success or failure - * of the write as a boolean YES or NO. */ - - /* FIXME: I believe that we should take the name of the file to be - * the cString of the path provided. It is unclear, however, that - * this is correct for fully internationalized functionality. If - * the cString <--> Unicode translation isn't completely - * bidirectional, this simple translation might not be the proper - * one. */ - - if (useAuxiliaryFile) - { - /* FIXME: Is it clear that using the tmpnam() system call is the - * right way to go? Do we need to worry about renaming the - * tempfile thus created, if we happen to be moving it across - * filesystems, for example? I don't think so. In particular, - * I think that this *is* a correct way to handle things. */ - theFileName = tmpnam(NULL); - theRealFileName = [path cString]; - } - else - { - theFileName = [path cString]; - } - - /* Open the file (whether temp or real) for writing. */ - theFile = fopen(theFileName, "w"); - - if (theFile == NULL) /* Something went wrong; we weren't - * even able to open the file. */ - goto failure; - - /* Now we try and write the NSData's bytes to the file. Here `c' is - * the number of bytes which were successfully written to the file - * in the fwrite() call. */ - /* FIXME: Do we need the `sizeof(char)' here? Is there any system - * where sizeof(char) isn't just 1? Or is it guaranteed to be 8 - * bits? */ - c = fwrite([self bytes], sizeof(char), [self length], theFile); - - if (c < [self length]) /* We failed to write everything for - * some reason. */ - goto failure; - - /* We're done, so close everything up. */ - c = fclose(theFile); - - if (c != 0) /* I can't imagine what went wrong - * closing the file, but we got here, - * so we need to deal with it. */ - goto failure; - - /* If we used a temporary file, we still need to rename() it be the - * real file. Am I forgetting anything here? */ - if (useAuxiliaryFile) - { - c = rename(theFileName, theRealFileName); - - if (c != 0) /* Many things could go wrong, I - * guess. */ - goto failure; - } - - /* success: */ - return YES; - - /* Just in case the failure action needs to be changed. */ - failure: - return NO; -} - - -/* - * Methos to handle deserializing. - */ -- (unsigned int) deserializeAlignedBytesLengthAtCursor:(unsigned int*)cursor -{ - return *cursor; -} - -- (void) deserializeBytes:(void*)buf - length:(unsigned int)bytes - atCursor:(unsigned int*)cursor -{ - NSRange range = { *cursor, bytes }; - [self getBytes:buf range:range]; - *cursor += bytes; -} - -- (void) deserializeDataAt:(void*)data - ofObjCType:(const char*)objType - atCursor:(unsigned int*)cursor - context:(id )callback -{ - if(!objType || !data) - return; - - switch(*objType) { - case _C_ID: { - [callback deserializeObjectAt:data ofObjCType:objType - fromData:self atCursor:cursor]; - break; - } - case _C_CHARPTR: { - int length = [self deserializeIntAtCursor:cursor]; - id adr = nil; - - if (length == -1) { - *(const char**)data = NULL; - return; - } - else { - OBJC_MALLOC (*(char**)data, char, length+1); - adr = [MallocAddress autoreleaseMallocAddress:*(void**)data]; - } - - [self deserializeBytes:*(char**)data length:length atCursor:cursor]; - (*(char**)data)[length] = '\0'; - [adr retain]; - - break; - } - case _C_ARY_B: { - int i, count, offset, itemSize; - const char* itemType; - - count = atoi(objType + 1); - itemType = objType; - while(isdigit(*++itemType)); - itemSize = objc_sizeof_type(itemType); - - for(i = offset = 0; i < count; i++, offset += itemSize) - [self deserializeDataAt:(char*)data + offset - ofObjCType:itemType - atCursor:cursor - context:callback]; - break; - } - case _C_STRUCT_B: { - int offset = 0; - int align, rem; - - while(*objType != _C_STRUCT_E && *objType++ != '=') - ; /* skip "=" */ - while(1) { - [self deserializeDataAt:((char*)data) + offset - ofObjCType:objType - atCursor:cursor - context:callback]; - offset += objc_sizeof_type(objType); - objType = objc_skip_typespec(objType); - if(*objType != _C_STRUCT_E) { - align = objc_alignof_type(objType); - if((rem = offset % align)) - offset += align - rem; - } - else break; - } - break; - } - case _C_PTR: { - id adr; - - OBJC_MALLOC (*(char**)data, char, objc_sizeof_type(++objType)); - adr = [MallocAddress autoreleaseMallocAddress:*(void**)data]; - - [self deserializeDataAt:*(char**)data - ofObjCType:objType - atCursor:cursor - context:callback]; - - [adr retain]; - - break; - } - case _C_CHR: - case _C_UCHR: { - [self deserializeBytes:data - length:sizeof(unsigned char) - atCursor:cursor]; - break; - } - case _C_SHT: - case _C_USHT: { - unsigned short ns; - - [self deserializeBytes:&ns - length:sizeof(unsigned short) - atCursor:cursor]; - *(unsigned short*)data = network_short_to_host (ns); - break; - } - case _C_INT: - case _C_UINT: { - unsigned int ni; - - [self deserializeBytes:&ni - length:sizeof(unsigned int) - atCursor:cursor]; - *(unsigned int*)data = network_int_to_host (ni); - break; - } - case _C_LNG: - case _C_ULNG: { - unsigned int nl; - - [self deserializeBytes:&nl - length:sizeof(unsigned long) - atCursor:cursor]; - *(unsigned long*)data = network_long_to_host (nl); - break; - } - case _C_FLT: { - network_float nf; - - [self deserializeBytes:&nf - length:sizeof(float) - atCursor:cursor]; - *(float*)data = network_float_to_host (nf); - break; - } - case _C_DBL: { - network_double nd; - - [self deserializeBytes:&nd - length:sizeof(double) - atCursor:cursor]; - *(double*)data = network_double_to_host (nd); - break; - } - default: - [NSException raise:NSGenericException - format:@"Unknown type to deserialize - '%s'", objType]; - } -} - -- (int) deserializeIntAtCursor:(unsigned int*)cursor -{ - unsigned int ni, result; - - [self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:cursor]; - result = network_int_to_host (ni); - return result; -} - -- (int) deserializeIntAtIndex:(unsigned int)index -{ - unsigned int ni; - - [self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:&index]; - return network_int_to_host (ni); -} - -- (void) deserializeInts:(int*)intBuffer - count:(unsigned int)numInts - atCursor:(unsigned int*)cursor -{ - unsigned i; - - [self deserializeBytes:&intBuffer - length:numInts * sizeof(unsigned int) - atCursor:cursor]; - for (i = 0; i < numInts; i++) - intBuffer[i] = network_int_to_host (intBuffer[i]); -} - -- (void) deserializeInts:(int*)intBuffer - count:(unsigned int)numInts - atIndex:(unsigned int)index -{ - unsigned i; - - [self deserializeBytes:&intBuffer - length:numInts * sizeof(int) - atCursor:&index]; - for (i = 0; i < numInts; i++) - intBuffer[i] = network_int_to_host (intBuffer[i]); -} - - -/* - * GNUstep extensions to NSData (for Streaming) - */ -+ (void) setVMChunk:(int)newValue -{ - if (newValue < 256) - { - newValue = 256; - } - if (newValue % 256) - { - newValue = ((newValue >> 8) + 1) << 8; - } - nsdata_vm_chunk = newValue; -} - -+ (void) setVMThreshold:(int)newValue -{ - if (newValue < 256) - { - newValue = 256; - } - nsdata_vm_threshold = newValue; -} - -+ (int)vmChunk -{ - return nsdata_vm_chunk; -} - -+ (int)vmThreshold -{ - return nsdata_vm_threshold; -} - -- (void) close -{ - [self flushStream]; -} - -- (void) flushStream -{ - /* Do nothing. */ -} - -- initOnBuffer: (void*)b /* data area or nul pointer */ - size: (unsigned)s /* size of the data area */ - type: (NSDataType)t /* type of storage to use */ - sharedMem: (int)m /* ID of shared memory segment */ - fileName: (NSString*)n /* name of mmap file. */ - eofPosition: (unsigned)l /* length of data for reading */ - position: (unsigned)i /* current pos for read/write */ - noCopy: (BOOL)f /* Adopt malloced data? */ -{ - self = [super init]; - if (self) - { -#if SHARED_SUPP == 0 - if (t == SHARED_DATA) t = MALLOC_DATA; -#else - if (f == NO && s >= nsdata_vm_threshold && t == MALLOC_DATA) - t = SHARED_DATA; -#endif -#if MAPPED_SUPP == 0 - if (t == MAPPED_DATA) t = MALLOC_DATA; -#endif - - if (l > s) /* Can't have eof_position > buffer size */ - l = s; - - if (i > l) /* Can't have position > eof_position */ - i = l; - - switch (t) - { - case STATIC_DATA: - buffer = b; - if (buffer == 0) - { - buffer = ""; - s = 0; - l = 0; - i = 0; - } - break; - -#if MAPPED_SUPP - case MAPPED_DATA: - if (n == nil) - { - [self dealloc]; - return nil; - } - else - { - int fd; - - if ([self isWritable]) - fd = open([n cStringNoCopy], O_RDWR); - else - fd = open([n cStringNoCopy], O_RDONLY); - if (fd < 0) - { - [self dealloc]; - return nil; - } - /* Find size of file to be mapped. */ - s = lseek(fd, 0, SEEK_END); - if (s < 0) - { - close(fd); - [self dealloc]; - return nil; - } - /* Position at start of file. */ - (void)lseek(fd, 0, SEEK_SET); - if ([self isWritable]) - buffer = mmap(0, s, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); - else - buffer = mmap(0, s, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); - if (buffer == MAP_FAILED) - { - buffer = 0; - [self dealloc]; - return nil; - } - l = s; - if (i > l) /* Can't have position > eof_position */ - i = l; - } - break; - -#endif -#if SHARED_SUPP - case SHARED_DATA: - if (m == 0) - { - struct shmid_ds buf; - - if ([self isWritable]) - if (s % nsdata_vm_chunk) - s = ((s / nsdata_vm_chunk) + 1) * nsdata_vm_chunk; - m = shmget(IPC_PRIVATE, s, IPC_CREAT|VM_ACCESS); - if (m == -1) /* Created memory? */ - { - [self dealloc]; - return nil; - } - buffer = shmat(m, 0, 0); - shmctl(m, IPC_RMID, &buf); /* Mark for later deletion. */ - if (buffer == (char*)-1) - { - buffer = 0; - [self dealloc]; - return nil; - } - shm_id = m; - if (l > 0) - memset(buffer, '\0', l); - } - else - { - struct shmid_ds buf; - - if (shmctl(m, IPC_STAT, &buf) < 0) - { - [self dealloc]; /* Unable to access memory. */ - return nil; - } - if (buf.shm_segsz < s) - { - [self dealloc]; /* Memory segment too small. */ - return nil; - } - buffer = shmat(m, 0, 0); - if (buffer == (char*)-1) - { - buffer = 0; - [self dealloc]; /* Unable to attach to memory. */ - return nil; - } - shm_id = m; - if (l > 0) - memcpy(buffer, b, l); - } - break; - -#endif - case MALLOC_DATA: - default: - if (f == YES) - buffer = b; /* We have been given control. */ - else - { /* Can't free it, so make copy */ - buffer = objc_malloc(s); - if (buffer == 0) - { - [self dealloc]; - return nil; - } - if (l > 0) - if (b == 0) - memset(buffer, '\0', l); - else - memcpy(buffer, b, l); - } - break; - } - type = t; - size = s; - eof_position = l; - position = i; - } - return self; -} - -- (id) initWithCapacity: (unsigned int)capacity -{ - return [self initOnBuffer:0 - size:capacity - type:MALLOC_DATA - sharedMem:0 - fileName:0 - eofPosition:0 - position:0 - noCopy:NO]; -} - -- (BOOL) isAtEof -{ - if (position == eof_position) - return YES; - return NO; -} - -- (BOOL) isClosed -{ - return NO; -} - -- (BOOL) isWritable -{ - return NO; -} - -- (int) readByte: (unsigned char*)b -{ - return [self readBytes:b length:1]; -} - -- (int) readBytes: (void*)b length: (int)l -{ - if (position+l > eof_position) - l = eof_position-position; - memcpy(b, buffer+position, l); - position += l; - return l; -} - -- (int) readFormat: (NSString*)format - arguments: (va_list)arg -{ - return 0; -} - -- (int) readFormat: (NSString*)format, ... -{ - int ret; - va_list ap; - - va_start(ap, format); - ret = o_vscanf(self, inchar_func, unchar_func, - [format cStringNoCopy], ap); - va_end(ap); - return ret; -} - -- (NSString*) readLine -{ - char *nl = memchr(buffer+position, '\n', eof_position-position); - char *ret = NULL; - if (nl) - { - int len = nl-buffer-position; - ret = objc_malloc (len+1); - strncpy(ret, buffer+position, len); - ret[len] = '\0'; - position += len+1; - } - return [[[NSString alloc] initWithCStringNoCopy: ret - length: ret ? strlen(ret) : 0 - freeWhenDone: YES] - autorelease]; -} - -- replacementObjectForPortCoder:(NSPortCoder*)aCoder -{ - return self; -} - -- (void) rewindStream -{ - [self setStreamPosition:0]; -} - -- (void) setFreeWhenDone: (BOOL)f -{ - [self notImplemented:_cmd]; -} - -- (void) setStreamBufferCapacity: (unsigned)s -{ - /* Nul operation for non-mutable object. */ -} - -- (void) setStreamEofPosition: (unsigned)i -{ - if (i < size) - eof_position = i; -} - -- (void) setStreamPosition: (unsigned)i seekMode: (seek_mode_t)mode -{ - int newposition = 0; - - switch (mode) - { - case STREAM_SEEK_FROM_START: - newposition = i; - break; - case STREAM_SEEK_FROM_CURRENT: - newposition += i; - break; - case STREAM_SEEK_FROM_END: - newposition = eof_position + i; - break; - } - if (newposition < 0) - newposition = 0; - if (newposition > eof_position) - { - [self setStreamEofPosition:newposition]; - position = eof_position; - } - else - position = newposition; -} - -- (void) setStreamPosition: (unsigned)i -{ - [self setStreamPosition: i seekMode: STREAM_SEEK_FROM_START]; -} - -- (char*) streamBuffer -{ - return 0; -} - -- (unsigned) streamBufferCapacity -{ - return size; -} - -- (unsigned) streamBufferLength -{ - return eof_position; -} - -- (BOOL) streamEof -{ - if (position == eof_position) - return YES; - else - return NO; -} - -- (unsigned) streamEofPosition -{ - return eof_position; -} - -- (unsigned) streamPosition -{ - return position; -} - -- (void)setVMThreshold: (int)size -{ - // Do nothing. -} - -- (int)vmThreshold -{ - return nsdata_vm_threshold; -} - -- (int) writeByte: (unsigned char)b -{ - /* Nul operation for non-mutable object. */ - return 0; -} - -- (int) writeBytes: (const void*)b length: (int)l -{ - /* Nul operation for non-mutable object. */ - return 0; -} - -- (int) writeFormat: (NSString*)format - arguments: (va_list)arg -{ - /* Nul operation for non-mutable object. */ - return 0; -} - -- (int) writeFormat: (NSString*)format, ... -{ - /* Nul operation for non-mutable object. */ - return 0; -} - -- (void) writeLine: (NSString*)l -{ - /* Nul operation for non-mutable object. */ -} - -@end - - -@implementation NSHMutableData - -+ allocWithZone:(NSZone *)zone -{ - return NSAllocateObject([NSHMutableData class], 0, zone); -} - -+ (id) dataWithCapacity: (unsigned int)numBytes -{ - return [[[self alloc] initWithCapacity:numBytes] autorelease]; -} - -+ (id) dataWithLength: (unsigned int)length -{ - return [[[self alloc] initWithLength:length] autorelease]; -} - -- (void)appendBytes:(const void*)b - length:(unsigned int)l -{ - if ((eof_position + l) >= size) - [self increaseCapacityBy:eof_position + l - size]; - memcpy(&buffer[eof_position], b, l); - eof_position += l; -} - -- (void) appendData: (NSData*)other -{ - [self appendBytes:[other bytes] length:[other length]]; -} - -- (void)increaseLengthBy:(unsigned int)extraLength -{ - [self setLength:[self length] + extraLength]; -} - -- (id) initWithLength: (unsigned int)length -{ - return [self initOnBuffer:0 - size:length - type:MALLOC_DATA - sharedMem:0 - fileName:0 - eofPosition:length - position:0 - noCopy:NO]; -} - -- (void*)mutableBytes -{ - return buffer; -} - -- (void) replaceBytesInRange: (NSRange)aRange - withBytes: (const void*)bytes -{ - if (aRange.location > size) - [NSException raise:NSRangeException - format:@"replacement location beyond end of data"]; - if (aRange.length == 0) - return; - if (aRange.location + aRange.length >= size) - [self increaseCapacityBy:aRange.location + aRange.length - size]; - memcpy([self mutableBytes] + aRange.location, bytes, aRange.length); -} - -- (void) resetBytesInRange: (NSRange)aRange -{ - if (aRange.location > size) - [NSException raise:NSRangeException - format:@"reset location beyond end of data"]; - if (aRange.length == 0) - return; - if (aRange.location + aRange.length >= size) - [self increaseCapacityBy:aRange.location + aRange.length - size]; - memset((char*)[self bytes] + aRange.location, 0, aRange.length); -} - -- (void) setData:(NSData*) other -{ - NSRange range; - - [self setLength:[other length]]; - range.location = 0; - range.length = [self length]; - [self replaceBytesInRange:range withBytes:[other bytes]]; -} - -- (void) setLength:(unsigned int)l -{ - [self setStreamEofPosition:l]; -} - - -/* - * Methods to handle serializing. - */ -- (void) serializeAlignedBytesLength:(unsigned int)length -{ -} - -- (void) serializeDataAt:(const void*)data - ofObjCType:(const char*)objType - context:(id )callback -{ - if(!data || !objType) - return; - - switch(*objType) { - case _C_ID: { - [callback serializeObjectAt:(id*)data - ofObjCType:objType - intoData:(NSMutableData*)self]; - break; - } - case _C_CHARPTR: { - int len; - - if(!*(void**)data) { - [self serializeInt:-1]; - return; - } - len = strlen(*(void**)data); - [self serializeInt:len]; - [self appendBytes:*(void**)data length:len]; - - break; - } - case _C_ARY_B: { - int i, offset, itemSize, count = atoi(objType + 1); - const char* itemType = objType; - - while(isdigit(*++itemType)); - itemSize = objc_sizeof_type(itemType); - - for(i = offset = 0; i < count; i++, offset += itemSize) - [self serializeDataAt:(char*)data + offset - ofObjCType:itemType - context:callback]; - - break; - } - case _C_STRUCT_B: { - int offset = 0; - int align, rem; - - while(*objType != _C_STRUCT_E && *objType++ != '=') - ; /* skip "=" */ - while(1) { - [self serializeDataAt:((char*)data) + offset - ofObjCType:objType - context:callback]; - offset += objc_sizeof_type(objType); - objType = objc_skip_typespec(objType); - if(*objType != _C_STRUCT_E) { - align = objc_alignof_type(objType); - if((rem = offset % align)) - offset += align - rem; - } - else break; - } - break; - } - case _C_PTR: - [self serializeDataAt:*(char**)data - ofObjCType:++objType context:callback]; - break; - case _C_CHR: - case _C_UCHR: - [self appendBytes:data length:sizeof(unsigned char)]; - break; - case _C_SHT: - case _C_USHT: { - unsigned short ns = host_short_to_network (*(unsigned short*)data); - [self appendBytes:&ns length:sizeof(unsigned short)]; - break; - } - case _C_INT: - case _C_UINT: { - unsigned int ni = host_int_to_network (*(unsigned int*)data); - [self appendBytes:&ni length:sizeof(unsigned int)]; - break; - } - case _C_LNG: - case _C_ULNG: { - unsigned long nl = host_long_to_network (*(unsigned long*)data); - [self appendBytes:&nl length:sizeof(unsigned long)]; - break; - } - case _C_FLT: { - network_float nf = host_float_to_network (*(float*)data); - [self appendBytes:&nf length:sizeof(float)]; - break; - } - case _C_DBL: { - network_double nd = host_double_to_network (*(double*)data); - [self appendBytes:&nd length:sizeof(double)]; - break; - } - default: - [NSException raise:NSGenericException - format:@"Unknown type to deserialize - '%s'", objType]; - } -} - -- (void) serializeInt:(int)value -{ - unsigned int ni = host_int_to_network (value); - [self appendBytes:&ni length:sizeof(unsigned int)]; -} - -- (void) serializeInt:(int)value - atIndex:(unsigned int)index -{ - unsigned int ni = host_int_to_network (value); - NSRange range = { index, sizeof(int) }; - [self replaceBytesInRange:range withBytes:&ni]; -} - -- (void) serializeInts:(int*)intBuffer - count:(unsigned int)numInts -{ - unsigned i; - SEL selector = @selector (serializeInt:); - IMP imp = [self methodForSelector:selector]; - - for (i = 0; i < numInts; i++) - (*imp)(self, selector, intBuffer[i]); -} - -- (void) serializeInts:(int*)intBuffer - count:(unsigned int)numInts - atIndex:(unsigned int)index -{ - unsigned i; - SEL selector = @selector (serializeInt:atIndex:); - IMP imp = [self methodForSelector:selector]; - - for (i = 0; i < numInts; i++) - (*imp)(self, selector, intBuffer[i], index++); -} - - -/* - * GNUstep extensions to NSHMutableData - */ -- (void)increaseCapacityBy:(unsigned int)extraCapacity -{ - [self setStreamBufferCapacity:size + extraCapacity]; -} - -- initOnBuffer: (void*)b /* data area or nul pointer */ - size: (unsigned)s /* size of the data area */ - type: (NSDataType)t /* type of storage to use */ - sharedMem: (int)m /* ID of shared memory segment */ - fileName: (NSString*)n /* name of mmap file. */ - eofPosition: (unsigned)l /* length of data for reading */ - position: (unsigned)i /* current pos for read/write */ - noCopy: (BOOL)f /* Adopt malloced data? */ -{ - self = [super initOnBuffer: b - size: s - type: t - sharedMem: m - fileName: n - eofPosition: l - position: i - noCopy: f]; - if (self) - vm_threshold = nsdata_vm_threshold; - return self; -} - -- (BOOL) isWritable -{ - return YES; -} - -/* - * Warning - this method raises an exception if no memory is available. - */ -- (void) setStreamBufferCapacity: (unsigned)s -{ - BOOL resize = NO; - int newtype = MALLOC_DATA; - - if (s > size) - resize = YES; -#if SHARED_SUPP - if (size >= [self vmThreshold]) - newtype = SHARED_DATA; - if (type == MALLOC_DATA) - resize = YES; - if (size < [self vmThreshold]) - newtype = MALLOC_DATA; - if (type == SHARED_DATA) - resize = YES; -#endif - - if (resize) - { - if (newtype == MALLOC_DATA) - { - if (buffer) - { - void* tmp = 0; - - if (type == MALLOC_DATA) - tmp = objc_realloc(buffer, s); - - if (tmp) - buffer = tmp; /* It worked. */ - else - { - tmp = objc_malloc(s); - if (tmp == 0) - [NSException raise:NSMallocException - format:@"Unable to malloc data - %s.", strerror(errno)]; - memcpy(tmp, buffer, position); - #if SHARED_SUPP - if (type == SHARED_DATA) - shmdt(buffer); - else - #endif - #if MAPPED_SUPP - if (type == MAPPED_DATA) - munmap(buffer, size); - else - #endif - if (type != STATIC_DATA) - objc_free(buffer); - buffer = tmp; - } - } - else - buffer = objc_malloc(s); - } -#if SHARED_SUPP - else - { - struct shmid_ds buf; - int shmid; - char* b; - - if (s % nsdata_vm_chunk) - s = ((s / nsdata_vm_chunk) + 1) * nsdata_vm_chunk; - shmid = shmget(IPC_PRIVATE, s, IPC_CREAT|VM_ACCESS); - if (shmid == -1) /* Created memory? */ - [NSException raise:NSMallocException - format:@"Unable to create shared memory segment - %s.", - strerror(errno)]; - b = shmat(shmid, 0, 0); - shmctl(shmid, IPC_RMID, &buf); /* Mark for later deletion. */ - if ((int)b == -1) /* Attached memory? */ - [NSException raise:NSMallocException - format:@"Unable to attach to shared memory segment."]; - if (eof_position > 0) - memcpy(b, buffer, eof_position); - if (buffer) - if (type == MALLOC_DATA) - objc_free(buffer); -#if MAPPED_SUPP - else if (type == MAPPED_DATA) - munmap(buffer, size); -#endif - else if (type == SHARED_DATA) - shmdt(buffer); - buffer = b; - shm_id = shmid; - } -#endif - size = s; - type = newtype; - } -} - -- (void) setStreamEofPosition: (unsigned)i -{ - if (i >= size) - [self setStreamBufferCapacity:i]; - [super setStreamEofPosition:i]; -} - -- (void) setVMThreshold:(int)s -{ - if (s < 256) - s = 256; - vm_threshold = s; - /* Force change in memory allocation if appropriate. */ - [self setStreamBufferCapacity:size]; -} - -- (char*) streamBuffer -{ - return buffer; -} - -- (int)vmThreshold -{ - return vm_threshold; -} - -- (int) writeByte: (unsigned char)b -{ - return [self writeBytes:&b length:1]; -} - -- (int) writeBytes: (const void*)b length: (int)l -{ - if (position+l > size) - { - unsigned int want = MAX(position+l, size*2); - - [self setStreamBufferCapacity: want]; - } - memcpy(buffer+position, b, l); - position += l; - if (position > eof_position) - eof_position = position; - return l; -} - -#if HAVE_VSPRINTF -- (int) writeFormat: (NSString*)format - arguments: (va_list)arg -{ - int ret; - - /* xxx Using this ugliness we at least let ourselves safely print - formatted strings up to 128 bytes long. - It's digusting, though, and we need to fix it. - Using GNU stdio streams would do the trick. - */ - if (size - position < 128) - [self setStreamBufferCapacity:position+128]; - - ret = VSPRINTF_LENGTH (vsprintf(buffer+position, - [format cStringNoCopy], arg)); - position += ret; - /* xxx Make sure we didn't overrun our buffer. - As per above kludge, this would happen if we happen to have more than - 128 bytes left in the buffer and we try to write a string longer than - the num bytes left in the buffer. */ - assert(position <= size); - if (position > eof_position) - eof_position = position; - return ret; -} -#else -- (int) writeFormat: (NSString*)format - arguments: (va_list)arg -{ - [self notImplemented:_cmd]; -} -#endif - -- (int) writeFormat: (NSString*)format, ... -{ - int ret; - va_list ap; - - va_start(ap, format); - ret = [self writeFormat: format arguments: ap]; - va_end(ap); - return ret; -} - -- (void) writeLine: (NSString*)l -{ - const char *s = [l cStringNoCopy]; - [self writeBytes:s length:strlen(s)]; - [self writeBytes:"\n" length:1]; -} -@end diff --git a/Source/NSPortCoder.m b/Source/NSPortCoder.m index 9e73220f6..8e1eb8c37 100644 --- a/Source/NSPortCoder.m +++ b/Source/NSPortCoder.m @@ -137,7 +137,7 @@ static BOOL debug_connected_coder = NO; return connection; } -- (BOOL) isByCopy +- (BOOL) isBycopy { return _is_by_copy; } @@ -172,12 +172,12 @@ static BOOL debug_connected_coder = NO; { BOOL old = _is_by_copy; id obj; + Class cls; _is_by_copy = NO; - obj = [anObj classForPortCoder: (NSPortCoder*)self]; - /* xxx Should I also do classname substition here? */ - [self encodeClass: obj]; obj = [anObj replacementObjectForPortCoder: (NSPortCoder*)self]; + cls = [obj classForPortCoder]; + [self encodeClass: cls]; [obj encodeWithCoder: (NSCoder*)self]; _is_by_copy = old; } @@ -188,7 +188,7 @@ static BOOL debug_connected_coder = NO; id obj; _is_by_copy = YES; - obj = [anObj classForPortCoder: (NSPortCoder*)self]; + obj = [anObj classForPortCoder]; [self encodeClass: obj]; obj = [anObj replacementObjectForPortCoder: (NSPortCoder*)self]; [obj encodeWithCoder: (NSCoder*)self]; @@ -422,7 +422,7 @@ static BOOL debug_connected_coder = NO; return 0; } -- (BOOL) isByCopy +- (BOOL) isBycopy { [self subclassResponsibility:_cmd]; return NO; @@ -446,12 +446,9 @@ static BOOL debug_connected_coder = NO; @implementation NSObject (NSPortCoder) /* By default, Object's encode themselves as proxies across Connection's */ -- (Class) classForPortCoder: (NSPortCoder*)aRmc +- (Class) classForPortCoder { - if ([aRmc isByCopy]) { - return [self class]; - } - return [[aRmc connection] proxyClass]; + return [self classForCoder]; } static inline BOOL class_is_kind_of (Class self, Class aClassObject) @@ -466,7 +463,7 @@ static inline BOOL class_is_kind_of (Class self, Class aClassObject) - replacementObjectForPortCoder: (NSPortCoder*)aRmc { - if ([aRmc isByCopy]) { + if ([aRmc isBycopy]) { return self; } else if (class_is_kind_of(object_get_class(self->isa), diff --git a/Source/NSString.m b/Source/NSString.m index 7cb965671..ed6993d98 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -2315,7 +2315,7 @@ else * deallocated in the other process - causing a memory leak. So we tell * the DO system to use the super class instead. */ -- (Class)classForPortCoder: (NSPortCoder*)aCoder +- (Class)classForPortCoder { return [self superclass]; } diff --git a/Source/Port.m b/Source/Port.m index a18f0c6b2..2df683986 100644 --- a/Source/Port.m +++ b/Source/Port.m @@ -69,7 +69,7 @@ return [self class]; } -- (Class) classForPortCoder: aRmc +- (Class) classForPortCoder { return [self class]; } diff --git a/Source/StdioStream.m b/Source/StdioStream.m index e9a149c93..cfc4df8d4 100644 --- a/Source/StdioStream.m +++ b/Source/StdioStream.m @@ -115,7 +115,8 @@ o_vscanf (void *stream, { id message; - message = [NSString stringWithFormat: @"Stream: %s", strerror(errno)]; + message = [[NSString alloc] initWithFormat: @"Stream: %s", + strerror(errno)]; NSLog(message); [message release]; [super dealloc]; @@ -131,7 +132,8 @@ o_vscanf (void *stream, { id message; - message = [NSString stringWithFormat: @"Stream: %s", strerror(errno)]; + message = [[NSString alloc] initWithFormat: @"Stream: %s", + strerror(errno)]; NSLog(message); [message release]; [super dealloc]; @@ -243,6 +245,7 @@ stdio_unchar_func(void *s, int c) - (void) close { fclose(fp); + fp = 0; } - (BOOL) isClosed diff --git a/Source/TcpPort.m b/Source/TcpPort.m index b49b14a92..276c60617 100644 --- a/Source/TcpPort.m +++ b/Source/TcpPort.m @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -1238,7 +1239,7 @@ assert(type == ET_RPORT); return [TcpOutPort class]; } -- (Class) classForPortCoder: aRmc +- (Class) classForPortCoder { return [TcpOutPort class]; } @@ -1686,7 +1687,7 @@ static NSMapTable *out_port_bag = NULL; [super dealloc]; } -- classForPortCoder: aRmc +- classForPortCoder { /* Make sure that Connection's always send us bycopy, i.e. as our own class, not a Proxy class. */ @@ -1840,15 +1841,15 @@ static NSMapTable *out_port_bag = NULL; int c; int remaining; - remaining = size - eof_position; + remaining = [data length] - prefix - eof_position; #ifdef GDOMAP - c = tryRead(s, 1, buffer + prefix + eof_position, -remaining); + c = tryRead(s, 1, [data mutableBytes] + prefix + eof_position, -remaining); #else /* xxx We need to make sure this read() is non-blocking. */ #ifdef __WIN32__ - c = recv (s, buffer + prefix + eof_position, remaining, 0); + c = recv (s, [data mutableBytes] + prefix + eof_position, remaining, 0); #else - c = read (s, buffer + prefix + eof_position, remaining); + c = read (s, [data mutableBytes] + prefix + eof_position, remaining); #endif /* __WIN32 */ #endif /* GDOMAP */ if (c <= 0) { @@ -1875,25 +1876,25 @@ static NSMapTable *out_port_bag = NULL; /* Put the packet size in the first two bytes of the packet. */ assert (prefix == PREFIX_SIZE); - *(PREFIX_LENGTH_TYPE*)buffer = htons (eof_position); + *(PREFIX_LENGTH_TYPE*)[data mutableBytes] = htons (eof_position); /* Put the sockaddr_in for replies in the next bytes of the prefix region. If there is no reply address specified, fill it with zeros. */ if (addr) /* Do this memcpy instead of simply casting the pointer because some systems fail to do the cast correctly (due to alignment issues?) */ - memcpy (buffer + PREFIX_LENGTH_SIZE, addr, PREFIX_ADDRESS_SIZE); + memcpy ([data mutableBytes]+PREFIX_LENGTH_SIZE, addr, PREFIX_ADDRESS_SIZE); else - memset (buffer + PREFIX_LENGTH_SIZE, 0, PREFIX_ADDRESS_SIZE); + memset ([data mutableBytes]+PREFIX_LENGTH_SIZE, 0, PREFIX_ADDRESS_SIZE); /* Write the packet on the socket. */ #ifdef GDOMAP - c = tryWrite (s, (int)timeout, buffer, prefix + eof_position); + c = tryWrite (s, (int)timeout, [data bytes], prefix + eof_position); #else #ifdef __WIN32__ - c = send (s, buffer, prefix + eof_position, 0); + c = send (s, [data bytes], prefix + eof_position, 0); #else - c = write (s, buffer, prefix + eof_position); + c = write (s, [data bytes], prefix + eof_position); #endif /* __WIN32__ */ #endif /* GDOMAP */ if (c == -2) { diff --git a/Source/UdpPort.m b/Source/UdpPort.m index 6a5df1062..bb2de971a 100644 --- a/Source/UdpPort.m +++ b/Source/UdpPort.m @@ -291,7 +291,7 @@ static NSMapTable *port_number_2_in_port = NULL; return [UdpOutPort class]; } -- (Class) classForPortCoder: aRmc +- (Class) classForPortCoder { return [UdpOutPort class]; } diff --git a/Source/UnixFileHandle.m b/Source/UnixFileHandle.m index 938128df7..c4b0beff9 100644 --- a/Source/UnixFileHandle.m +++ b/Source/UnixFileHandle.m @@ -69,7 +69,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) struct servent* sp; if (svc == nil) - return NO; + svc = @"localhost"; if (pcl) proto = [pcl cStringNoCopy]; @@ -174,21 +174,17 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) int net; struct sockaddr_in sin; - if (address == nil) - { - [self release]; - return nil; - } - if (getAddr(address, service, protocol, &sin) == NO) { - [self release]; + [self dealloc]; + NSLog(@"bad address-service-protocol combination"); return nil; } if ((net = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { - [self release]; + [self dealloc]; + NSLog(@"unable to create socket - %s", strerror(errno)); return nil; } @@ -201,7 +197,8 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (connect(net, (struct sockaddr*)&sin, sizeof(sin)) < 0) if (errno != EINPROGRESS) { - [self release]; + [self dealloc]; + NSLog(@"unable to make connection - %s", strerror(errno)); return nil; } @@ -214,10 +211,10 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) [writeInfo addObject:info]; [info release]; [self watchWriteDescriptor]; + connectOK = YES; + readOK = NO; + writeOK = NO; } - connectOK = YES; - readOK = NO; - writeOK = NO; return self; } @@ -231,13 +228,15 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (getAddr(address, service, protocol, &sin) == NO) { - [self release]; - return nil; + [self dealloc]; + NSLog(@"bad address-service-protocol combination"); + return nil; } if ((net = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { - [self release]; + [self dealloc]; + NSLog(@"unable to create socket - %s", strerror(errno)); return nil; } @@ -246,21 +245,26 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (bind(net, (struct sockaddr *)&sin, sizeof(sin)) < 0) { (void) close(net); - [self release]; + [self dealloc]; + NSLog(@"unable to bind to port - %s", strerror(errno)); return nil; } if (listen(net, 5) < 0) { (void) close(net); - [self release]; + [self dealloc]; + NSLog(@"unable to listen on port - %s", strerror(errno)); return nil; } self = [self initWithFileDescriptor:net closeOnDealloc:YES]; - acceptOK = YES; - readOK = NO; - writeOK = NO; + if (self) + { + acceptOK = YES; + readOK = NO; + writeOK = NO; + } return self; } @@ -270,13 +274,14 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (d < 0) { - [self release]; + [self dealloc]; return nil; } else { self = [self initWithFileDescriptor:d closeOnDealloc:YES]; - writeOK = NO; + if (self) + writeOK = NO; return self; } } @@ -287,13 +292,14 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (d < 0) { - [self release]; + [self dealloc]; return nil; } else { self = [self initWithFileDescriptor:d closeOnDealloc:YES]; - readOK = NO; + if (self) + readOK = NO; return self; } } @@ -304,7 +310,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (d < 0) { - [self release]; + [self dealloc]; return nil; } else @@ -318,7 +324,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (fh_stderr) { [fh_stderr retain]; - [self release]; + [self dealloc]; } else { @@ -326,8 +332,8 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) fh_stderr = self; } self = fh_stderr; - readOK = NO; - return self; + if (self) + readOK = NO; return self; } @@ -336,7 +342,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (fh_stdin) { [fh_stdin retain]; - [self release]; + [self dealloc]; } else { @@ -344,7 +350,8 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) fh_stdin = self; } self = fh_stdin; - writeOK = NO; + if (self) + writeOK = NO; return self; } @@ -353,7 +360,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (fh_stdout) { [fh_stdout retain]; - [self release]; + [self dealloc]; } else { @@ -361,7 +368,8 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) fh_stdout = self; } self = fh_stdout; - readOK = NO; + if (self) + readOK = NO; return self; } @@ -384,9 +392,11 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) int e; if (fstat(desc, &sbuf) < 0) - [NSException raise: NSFileHandleOperationException - format: @"unable to get status of descriptor - %s", - strerror(errno)]; + { + [self dealloc]; + NSLog(@"unable to get status of descriptor - %s", strerror(errno)); + return nil; + } if (S_ISREG(sbuf.st_mode)) isStandardFile = YES; else @@ -732,12 +742,9 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) - (void)closeFile { - NSNotification* n; - - /* Ensure that any notifications we queued are destroyed with us. */ - n = [NSNotification notificationWithName:@"any" object:self userInfo:nil]; - [[NSNotificationQueue defaultQueue] dequeueNotificationsMatching:n - coalesceMask:NSNotificationCoalescingOnSender]; + if (descriptor < 0) + [NSException raise: NSFileHandleOperationException + format: @"attempt to close closed file"]; [self ignoreReadDescriptor]; [self ignoreWriteDescriptor]; @@ -851,12 +858,15 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) - (void)ignoreReadDescriptor { - NSRunLoop* l = [NSRunLoop currentRunLoop]; - NSArray* modes = nil; + NSRunLoop *l; + NSArray *modes; if (descriptor < 0) return; + l = [NSRunLoop currentRunLoop]; + modes = nil; + if (readInfo) modes = (NSArray*)[readInfo objectForKey:NSFileHandleNotificationMonitorModes]; @@ -881,12 +891,15 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) - (void)ignoreWriteDescriptor { - NSRunLoop* l = [NSRunLoop currentRunLoop]; - NSArray* modes = nil; + NSRunLoop *l; + NSArray *modes; if (descriptor < 0) return; + l = [NSRunLoop currentRunLoop]; + modes = nil; + if ([writeInfo count] > 0) { NSMutableDictionary* info = [writeInfo objectAtIndex:0]; @@ -915,7 +928,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) - (void)watchReadDescriptorForModes:(NSArray*)modes; { - NSRunLoop* l; + NSRunLoop *l; if (descriptor < 0) return; @@ -986,7 +999,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) extra: (void*)extra forMode: (NSString*)mode { - NSString* operation; + NSString *operation; if (type == ET_RDESC) { operation = [readInfo objectForKey:NotificationKey]; @@ -1115,13 +1128,12 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) e &= ~NBLK_OPT; if (fcntl(descriptor, F_SETFL, e) < 0) - [NSException raise: NSFileHandleOperationException - format: @"could not change non-blocking mode"]; - isNonBlocking = flag; + NSLog(@"unable to set non-blocking mode - %s", strerror(errno)); + else + isNonBlocking = flag; } else - [NSException raise: NSFileHandleOperationException - format: @"could not change non-blocking mode"]; + NSLog(@"unable to get non-blocking mode - %s", strerror(errno)); } @end diff --git a/Testing/nsdata.m b/Testing/nsdata.m index afaf572bc..f03ebc9a8 100644 --- a/Testing/nsdata.m +++ b/Testing/nsdata.m @@ -1,11 +1,14 @@ #include +#include #include #include int main() { + id a; id d; + id o; id pool; pool = [[NSAutoreleasePool alloc] init]; @@ -14,7 +17,76 @@ main() if (d == nil) printf("Unable to map file"); printf("Mapped %d bytes\n", [d length]); + + o = [d copy]; + printf("Copied %d bytes\n", [o length]); + [o release]; + + o = [d mutableCopy]; + printf("Copied %d bytes\n", [o length]); + [o release]; + + d = [NSData dataWithContentsOfFile:@"nsdata.m"]; + if (d == nil) + printf("Unable to read file"); + printf("Read %d bytes\n", [d length]); + + o = [d copy]; + printf("Copied %d bytes\n", [o length]); + [o release]; + + o = [d mutableCopy]; + printf("Copied %d bytes\n", [o length]); + [o release]; + + d = [NSData dataWithSharedBytes: [d bytes] length: [d length]]; + if (d == nil) + printf("Unable to make shared data"); + printf("Shared data of %d bytes\n", [d length]); + + o = [d copy]; + printf("Copied %d bytes\n", [o length]); + [o release]; + + o = [d mutableCopy]; + printf("Copied %d bytes\n", [o length]); + [o release]; + + d = [NSMutableData dataWithSharedBytes: [d bytes] length: [d length]]; + if (d == nil) + printf("Unable to make mutable shared data"); + printf("Mutable shared data of %d bytes\n", [d length]); + + o = [d copy]; + printf("Copied %d bytes\n", [o length]); + [o release]; + + o = [d mutableCopy]; + printf("Copied %d bytes\n", [o length]); + [o release]; + + [d appendBytes: "Hello world" length: 11]; + printf("Extended by 11 bytes to %d bytes\n", [d length]); + + d = [NSMutableData dataWithShmID: [d shmID] length: [d length]]; + if (d == nil) + printf("Unable to make mutable data with old ID\n"); + printf("data with shmID gives data length %d\n", [d length]); + + a = [[NSArchiver new] autorelease]; + [a encodeRootObject: d]; + printf("Encoded data into archive\n"); + a = [[NSUnarchiver alloc] initForReadingWithData: [a archiverData]]; + o = [a decodeObject]; + printf("Decoded data from archive - length %d\n", [o length]); + [a release]; + [o release]; + + [d setCapacity: 2000000]; + printf("Set capacity of shared memory item to %d\n", [d capacity]); + [pool release]; exit(0); } + diff --git a/Testing/oldserver.h b/Testing/oldserver.h index 80e0b7b1e..80e6cdf5f 100644 --- a/Testing/oldserver.h +++ b/Testing/oldserver.h @@ -5,10 +5,10 @@ #include #include -typedef struct _small_struct { +typedef struct _small_struct { unsigned char z; } small_struct; - + typedef struct _foo { int i; char *s;