1995-04-09 02:20:37 +00:00
|
|
|
|
/* Stream of bytes class for serialization and persistance in GNUStep
|
1997-09-29 14:39:53 +00:00
|
|
|
|
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1996-04-17 20:17:45 +00:00
|
|
|
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
1995-04-09 02:20:37 +00:00
|
|
|
|
Date: March 1995
|
1997-09-29 14:39:53 +00:00
|
|
|
|
Rewritten by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
|
|
|
|
Date: September 1997
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
|
This file is part of the GNUstep Base Library.
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
/* 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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
1997-11-06 00:51:23 +00:00
|
|
|
|
#include <config.h>
|
1997-12-11 19:09:56 +00:00
|
|
|
|
#include <objc/objc-api.h>
|
1996-04-17 15:34:35 +00:00
|
|
|
|
#include <gnustep/base/preface.h>
|
1998-03-06 18:13:53 +00:00
|
|
|
|
#include <Foundation/NSByteOrder.h>
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#include <Foundation/NSCoder.h>
|
1995-04-17 21:13:20 +00:00
|
|
|
|
#include <Foundation/NSData.h>
|
|
|
|
|
#include <Foundation/NSString.h>
|
1995-04-21 00:11:21 +00:00
|
|
|
|
#include <Foundation/NSException.h>
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#include <Foundation/NSDebug.h>
|
1996-03-18 13:55:26 +00:00
|
|
|
|
#include <string.h> /* for memset() */
|
1997-09-01 21:59:51 +00:00
|
|
|
|
#include <unistd.h> /* SEEK_* on SunOS 4 */
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#if HAVE_MMAP
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#ifndef MAP_FAILED
|
|
|
|
|
#define MAP_FAILED ((void*)-1) /* Failure address. */
|
|
|
|
|
#endif
|
|
|
|
|
@class NSDataMappedFile;
|
|
|
|
|
#endif
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#if HAVE_SHMCTL
|
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
|
#include <sys/shm.h>
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1997-10-28 14:34:49 +00:00
|
|
|
|
#define VM_RDONLY 0644 /* self read/write - other readonly */
|
|
|
|
|
#define VM_ACCESS 0666 /* read/write access for all */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@class NSDataShared;
|
|
|
|
|
@class NSMutableDataShared;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
@class NSDataMalloc;
|
|
|
|
|
@class NSDataStatic;
|
|
|
|
|
@class NSMutableDataMalloc;
|
1995-07-03 22:10:49 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
|
|
|
|
static BOOL
|
1998-10-15 05:03:16 +00:00
|
|
|
|
readContentsOfFile(NSString* path, void** buf, unsigned* len, NSZone* zone)
|
1995-07-03 22:10:49 +00:00
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
char thePath[BUFSIZ*2];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
FILE *theFile = 0;
|
|
|
|
|
unsigned int fileLength;
|
|
|
|
|
void *tmp = 0;
|
|
|
|
|
int c;
|
|
|
|
|
|
1998-02-03 14:20:00 +00:00
|
|
|
|
if ([path getFileSystemRepresentation: thePath
|
|
|
|
|
maxLength: sizeof(thePath)-1] == NO)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Open (%s) attempt failed - bad path", thePath);
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
theFile = fopen(thePath, "r");
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
|
|
|
|
if (theFile == NULL) /* We failed to open the file. */
|
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"Open (%s) attempt failed - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Seek to the end of the file. */
|
|
|
|
|
c = fseek(theFile, 0L, SEEK_END);
|
|
|
|
|
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(). */
|
|
|
|
|
fileLength = ftell(theFile);
|
|
|
|
|
if (fileLength == -1)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Ftell failed - %s", strerror(errno));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
tmp = NSZoneMalloc(zone, fileLength);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Fseek to start of file failed - %s", strerror(errno));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = fread(tmp, 1, fileLength, theFile);
|
|
|
|
|
if (c != fileLength)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Fread of file contents failed - %s", strerror(errno));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*buf = tmp;
|
|
|
|
|
*len = fileLength;
|
1998-02-03 14:20:00 +00:00
|
|
|
|
fclose(theFile);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
|
|
/* Just in case the failure action needs to be changed. */
|
|
|
|
|
failure:
|
|
|
|
|
if (tmp)
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZoneFree(zone, tmp);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
if (theFile)
|
|
|
|
|
fclose(theFile);
|
|
|
|
|
return NO;
|
1995-07-03 22:10:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
|
|
|
|
@interface NSDataMalloc : NSData
|
1995-07-03 22:10:49 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
unsigned int length;
|
|
|
|
|
void *bytes;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZone *zone;
|
1995-07-03 22:10:49 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@end
|
1995-07-03 22:10:49 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@interface NSMutableDataMalloc : NSMutableData
|
1995-07-03 22:10:49 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
unsigned int capacity;
|
|
|
|
|
unsigned int length;
|
|
|
|
|
void *bytes;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZone *zone;
|
1995-07-03 22:10:49 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
#if HAVE_MMAP
|
|
|
|
|
@interface NSDataMappedFile : NSDataMalloc
|
|
|
|
|
@end
|
|
|
|
|
#endif
|
1995-07-03 22:10:49 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#if HAVE_SHMCTL
|
|
|
|
|
@interface NSDataShared : NSDataMalloc
|
1995-07-03 22:10:49 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
int shmid;
|
1995-07-03 22:10:49 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (id) initWithShmID: (int)anId length: (unsigned)bufferSize;
|
|
|
|
|
@end
|
1995-07-03 22:10:49 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@interface NSMutableDataShared : NSMutableDataMalloc
|
1995-07-03 22:10:49 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
int shmid;
|
1995-07-03 22:10:49 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (id) initWithShmID: (int)anId length: (unsigned)bufferSize;
|
|
|
|
|
@end
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
@interface NSDataStatic: NSDataMalloc
|
|
|
|
|
@end
|
1995-07-03 22:10:49 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
|
|
|
|
@implementation NSData
|
|
|
|
|
+ (NSData*) allocWithZone: (NSZone*)z
|
1995-08-23 15:36:59 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return (NSData*)NSAllocateObject([NSDataMalloc class], 0, z);
|
1995-08-23 15:36:59 +00:00
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
|
|
|
|
+ (id) data
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [[[NSDataStatic alloc] initWithBytesNoCopy: 0 length: 0]
|
1995-04-09 02:20:37 +00:00
|
|
|
|
autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (id) dataWithBytes: (const void*)bytes
|
1997-09-29 14:39:53 +00:00
|
|
|
|
length: (unsigned int)length
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [[[NSDataMalloc alloc] initWithBytes:bytes length:length]
|
1995-04-09 02:20:37 +00:00
|
|
|
|
autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (id) dataWithBytesNoCopy: (void*)bytes
|
1997-09-29 14:39:53 +00:00
|
|
|
|
length: (unsigned int)length
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [[[NSDataMalloc alloc] initWithBytesNoCopy:bytes length:length]
|
1995-04-09 02:20:37 +00:00
|
|
|
|
autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
+ (id) dataWithContentsOfFile: (NSString*)path
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [[[NSDataMalloc alloc] initWithContentsOfFile:path]
|
1995-04-20 16:04:56 +00:00
|
|
|
|
autorelease];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (id) dataWithContentsOfMappedFile: (NSString*)path
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#if HAVE_MMAP
|
|
|
|
|
return [[[NSDataMappedFile alloc] initWithContentsOfMappedFile:path]
|
|
|
|
|
autorelease];
|
|
|
|
|
#else
|
|
|
|
|
return [[[NSDataMalloc alloc] initWithContentsOfMappedFile:path]
|
1995-04-20 16:02:26 +00:00
|
|
|
|
autorelease];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#endif
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-01-19 15:20:15 +00:00
|
|
|
|
+ (id) dataWithData: (NSData*)data
|
|
|
|
|
{
|
|
|
|
|
return [[[NSDataMalloc alloc] initWithBytes: [data bytes]
|
|
|
|
|
length: [data length]] autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
- (id) init
|
1995-08-02 14:51:26 +00:00
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
return [self initWithBytesNoCopy: 0 length: 0];
|
1995-08-02 14:51:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
- (id) initWithBytes: (const void*)aBuffer
|
|
|
|
|
length: (unsigned int)bufferSize
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1995-08-02 14:51:26 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
|
|
|
|
length: (unsigned int)bufferSize
|
|
|
|
|
{
|
|
|
|
|
if (aBuffer)
|
|
|
|
|
return [self initWithBytesNoCopy: aBuffer
|
|
|
|
|
length: bufferSize
|
|
|
|
|
fromZone: NSZoneFromPointer(aBuffer)];
|
|
|
|
|
else
|
|
|
|
|
return [self initWithBytesNoCopy: aBuffer
|
|
|
|
|
length: bufferSize
|
|
|
|
|
fromZone: [self zone]];
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-20 16:02:26 +00:00
|
|
|
|
- (id) initWithContentsOfFile: (NSString *)path
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-20 16:02:26 +00:00
|
|
|
|
return nil;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-04-20 16:02:26 +00:00
|
|
|
|
- (id) initWithContentsOfMappedFile: (NSString *)path;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
|
return nil;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithData: (NSData*)data
|
|
|
|
|
{
|
|
|
|
|
return [self initWithBytes:[data bytes] length:[data length]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Accessing Data
|
|
|
|
|
|
|
|
|
|
- (const void*) bytes
|
|
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSString*) description
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
NSString *str;
|
|
|
|
|
const char *src = [self bytes];
|
|
|
|
|
char *dest;
|
|
|
|
|
int length = [self length];
|
|
|
|
|
int i,j;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZone *z = [self zone];
|
1996-05-13 16:43:29 +00:00
|
|
|
|
|
|
|
|
|
#define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57))
|
|
|
|
|
|
|
|
|
|
/* we can just build a cString and convert it to an NSString */
|
1998-10-15 05:03:16 +00:00
|
|
|
|
dest = (char*) NSZoneMalloc(z, 2*length+length/4+3);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
if (dest == 0)
|
|
|
|
|
[NSException raise:NSMallocException
|
|
|
|
|
format:@"No memory for description of NSData object"];
|
1996-05-13 16:43:29 +00:00
|
|
|
|
dest[0] = '<';
|
|
|
|
|
for (i=0,j=1; i<length; i++,j++)
|
|
|
|
|
{
|
|
|
|
|
dest[j++] = num2char((src[i]>>4) & 0x0f);
|
|
|
|
|
dest[j] = num2char(src[i] & 0x0f);
|
1998-01-19 15:20:15 +00:00
|
|
|
|
if((i&0x3) == 3 && i != length-1)
|
1996-05-13 16:43:29 +00:00
|
|
|
|
/* if we've just finished a 32-bit int, print a space */
|
|
|
|
|
dest[++j] = ' ';
|
|
|
|
|
}
|
|
|
|
|
dest[j++] = '>';
|
|
|
|
|
dest[j] = '\0';
|
1998-10-15 05:03:16 +00:00
|
|
|
|
str = [[[NSString alloc] initWithCStringNoCopy: dest length: j fromZone: z]
|
|
|
|
|
autorelease];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return str;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)getBytes: (void*)buffer
|
|
|
|
|
{
|
|
|
|
|
[self getBytes:buffer length:[self length]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)getBytes: (void*)buffer
|
1997-09-29 14:39:53 +00:00
|
|
|
|
length: (unsigned int)length
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1998-09-30 19:22:11 +00:00
|
|
|
|
[self getBytes:buffer range: NSMakeRange(0, length)];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)getBytes: (void*)buffer
|
1997-09-29 14:39:53 +00:00
|
|
|
|
range: (NSRange)aRange
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
auto int size;
|
|
|
|
|
|
|
|
|
|
// Check for 'out of range' errors. This code assumes that the
|
|
|
|
|
// NSRange location and length types will remain unsigned (hence
|
|
|
|
|
// the lack of a less-than-zero check).
|
|
|
|
|
size = [self length];
|
1997-10-16 23:56:27 +00:00
|
|
|
|
if (aRange.location > size ||
|
|
|
|
|
aRange.length > size ||
|
1997-09-01 21:59:51 +00:00
|
|
|
|
NSMaxRange( aRange ) > size)
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"Range: (%u, %u) Size: %d",
|
|
|
|
|
aRange.location, aRange.length, size];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
else
|
|
|
|
|
memcpy(buffer, [self bytes] + aRange.location, aRange.length);
|
|
|
|
|
return;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-10-28 14:37:53 +00:00
|
|
|
|
- (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-09 02:20:37 +00:00
|
|
|
|
- (NSData*) subdataWithRange: (NSRange)aRange
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
void *buffer;
|
|
|
|
|
unsigned l = [self 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];
|
1997-10-16 23:56:27 +00:00
|
|
|
|
if (aRange.location > l || aRange.length > l || NSMaxRange(aRange) > l)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"Range: (%u, %u) Size: %d",
|
|
|
|
|
aRange.location, aRange.length, l];
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
buffer = NSZoneMalloc([self zone], aRange.length);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
if (buffer == 0)
|
|
|
|
|
[NSException raise:NSMallocException
|
|
|
|
|
format:@"No memory for subdata of NSData object"];
|
1995-04-20 16:02:26 +00:00
|
|
|
|
[self getBytes:buffer range:aRange];
|
|
|
|
|
|
|
|
|
|
return [NSData dataWithBytesNoCopy:buffer length:aRange.length];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (unsigned int) hash
|
|
|
|
|
{
|
|
|
|
|
return [self length];
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-13 15:03:10 +00:00
|
|
|
|
- (BOOL) isEqual: anObject
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
if ([anObject isKindOfClass:[NSData class]])
|
1995-04-13 15:03:10 +00:00
|
|
|
|
return [self isEqualToData:anObject];
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
|
|
|
|
// Querying a Data Object
|
|
|
|
|
- (BOOL) isEqualToData: (NSData*)other;
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
if ((len = [self length]) != [other length])
|
|
|
|
|
return NO;
|
|
|
|
|
return (memcmp([self bytes], [other bytes], len) ? NO : YES);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned int)length;
|
|
|
|
|
{
|
1995-04-20 16:02:26 +00:00
|
|
|
|
/* This is left to concrete subclasses to implement. */
|
1996-02-01 17:04:17 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Storing Data
|
|
|
|
|
|
1995-04-20 16:02:26 +00:00
|
|
|
|
- (BOOL) writeToFile: (NSString *)path
|
1997-09-29 14:39:53 +00:00
|
|
|
|
atomically: (BOOL)useAuxiliaryFile
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
char thePath[BUFSIZ*2+8];
|
|
|
|
|
char theRealPath[BUFSIZ*2];
|
1995-04-20 16:02:26 +00:00
|
|
|
|
FILE *theFile;
|
|
|
|
|
int c;
|
|
|
|
|
|
1998-02-03 14:20:00 +00:00
|
|
|
|
if ([path getFileSystemRepresentation: theRealPath
|
|
|
|
|
maxLength: sizeof(theRealPath)-1] == NO)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Open (%s) attempt failed - bad path", theRealPath);
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
|
|
|
|
if (useAuxiliaryFile)
|
|
|
|
|
{
|
1997-10-31 16:26:44 +00:00
|
|
|
|
/* Use the path name of the destination file as a prefix for the
|
|
|
|
|
* mktemp() call so that we can be sure that both files are on
|
|
|
|
|
* the same filesystem and the subsequent rename() will work. */
|
1998-02-03 14:20:00 +00:00
|
|
|
|
strcpy(thePath, theRealPath);
|
|
|
|
|
strcat(thePath, "XXXXXX");
|
|
|
|
|
if (mktemp(thePath) == 0)
|
1997-10-31 16:26:44 +00:00
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"mktemp (%s) failed - %s", thePath, strerror(errno));
|
1997-10-31 16:26:44 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
strcpy(thePath, theRealPath);
|
1995-04-20 16:02:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open the file (whether temp or real) for writing. */
|
1998-02-03 14:20:00 +00:00
|
|
|
|
theFile = fopen(thePath, "w");
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
|
|
|
|
if (theFile == NULL) /* Something went wrong; we weren't
|
|
|
|
|
* even able to open the file. */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"Open (%s) failed - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
|
c = fwrite([self bytes], sizeof(char), [self length], theFile);
|
|
|
|
|
|
|
|
|
|
if (c < [self length]) /* We failed to write everything for
|
|
|
|
|
* some reason. */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"Fwrite (%s) failed - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
|
|
|
|
/* 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. */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"Fclose (%s) failed - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
|
|
|
|
/* If we used a temporary file, we still need to rename() it be the
|
|
|
|
|
* real file. Am I forgetting anything here? */
|
|
|
|
|
if (useAuxiliaryFile)
|
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
c = rename(thePath, theRealPath);
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
|
|
|
|
if (c != 0) /* Many things could go wrong, I
|
|
|
|
|
* guess. */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"Rename (%s) failed - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* success: */
|
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
|
|
/* Just in case the failure action needs to be changed. */
|
|
|
|
|
failure:
|
1995-04-09 02:20:37 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
1995-04-09 02:20:37 +00:00
|
|
|
|
// Deserializing Data
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (unsigned int)deserializeAlignedBytesLengthAtCursor:(unsigned int*)cursor
|
|
|
|
|
{
|
|
|
|
|
return *cursor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)deserializeBytes:(void*)buffer
|
1997-09-29 14:39:53 +00:00
|
|
|
|
length:(unsigned int)bytes
|
|
|
|
|
atCursor:(unsigned int*)cursor
|
1997-09-01 21:59:51 +00:00
|
|
|
|
{
|
|
|
|
|
NSRange range = { *cursor, bytes };
|
|
|
|
|
[self getBytes:buffer range:range];
|
|
|
|
|
*cursor += bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)deserializeDataAt:(void*)data
|
1997-09-29 14:39:53 +00:00
|
|
|
|
ofObjCType:(const char*)type
|
|
|
|
|
atCursor:(unsigned int*)cursor
|
|
|
|
|
context:(id <NSObjCTypeSerializationCallBack>)callback
|
1997-09-01 21:59:51 +00:00
|
|
|
|
{
|
|
|
|
|
if(!type || !data)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
switch(*type) {
|
|
|
|
|
case _C_ID: {
|
|
|
|
|
[callback deserializeObjectAt:data ofObjCType:type
|
|
|
|
|
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 {
|
1998-09-30 08:24:05 +00:00
|
|
|
|
unsigned len = (length+1)*sizeof(char);
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
*(char**)data = (char*)NSZoneMalloc([self zone], len);
|
1998-09-30 08:24:05 +00:00
|
|
|
|
adr = [NSData dataWithBytesNoCopy: *(void**)data length: len];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[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(type + 1);
|
|
|
|
|
itemType = type;
|
|
|
|
|
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(*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
|
|
|
|
while(1) {
|
|
|
|
|
[self deserializeDataAt:((char*)data) + offset
|
|
|
|
|
ofObjCType:type
|
|
|
|
|
atCursor:cursor
|
|
|
|
|
context:callback];
|
|
|
|
|
offset += objc_sizeof_type(type);
|
|
|
|
|
type = objc_skip_typespec(type);
|
|
|
|
|
if(*type != _C_STRUCT_E) {
|
|
|
|
|
align = objc_alignof_type(type);
|
|
|
|
|
if((rem = offset % align))
|
|
|
|
|
offset += align - rem;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_PTR: {
|
1998-09-30 08:24:05 +00:00
|
|
|
|
unsigned len = objc_sizeof_type(++type);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
id adr;
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
*(char**)data = (char*)NSZoneMalloc([self zone], len);
|
1998-09-30 08:24:05 +00:00
|
|
|
|
adr = [NSData dataWithBytesNoCopy: *(void**)data length: len];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
|
|
|
|
[self deserializeDataAt:*(char**)data
|
|
|
|
|
ofObjCType:type
|
|
|
|
|
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];
|
1998-03-06 18:13:53 +00:00
|
|
|
|
*(unsigned short*)data = NSSwapBigShortToHost (ns);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_INT:
|
|
|
|
|
case _C_UINT: {
|
|
|
|
|
unsigned int ni;
|
|
|
|
|
|
|
|
|
|
[self deserializeBytes:&ni
|
|
|
|
|
length:sizeof(unsigned int)
|
|
|
|
|
atCursor:cursor];
|
1998-03-06 18:13:53 +00:00
|
|
|
|
*(unsigned int*)data = NSSwapBigIntToHost (ni);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_LNG:
|
|
|
|
|
case _C_ULNG: {
|
|
|
|
|
unsigned int nl;
|
|
|
|
|
|
|
|
|
|
[self deserializeBytes:&nl
|
|
|
|
|
length:sizeof(unsigned long)
|
|
|
|
|
atCursor:cursor];
|
1998-03-06 18:13:53 +00:00
|
|
|
|
*(unsigned long*)data = NSSwapBigLongToHost (nl);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_FLT: {
|
1998-03-06 18:13:53 +00:00
|
|
|
|
NSSwappedFloat nf;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
|
|
|
|
[self deserializeBytes:&nf
|
1998-03-06 18:13:53 +00:00
|
|
|
|
length:sizeof(NSSwappedFloat)
|
1997-09-01 21:59:51 +00:00
|
|
|
|
atCursor:cursor];
|
1998-03-06 18:13:53 +00:00
|
|
|
|
*(float*)data = NSSwapBigFloatToHost (nf);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_DBL: {
|
1998-03-06 18:13:53 +00:00
|
|
|
|
NSSwappedDouble nd;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
|
|
|
|
[self deserializeBytes:&nd
|
1998-03-06 18:13:53 +00:00
|
|
|
|
length:sizeof(NSSwappedDouble)
|
1997-09-01 21:59:51 +00:00
|
|
|
|
atCursor:cursor];
|
1998-03-06 18:13:53 +00:00
|
|
|
|
*(double*)data = NSSwapBigDoubleToHost (nd);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
[NSException raise:NSGenericException
|
|
|
|
|
format:@"Unknown type to deserialize - '%s'", type];
|
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (int)deserializeIntAtCursor:(unsigned int*)cursor
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
unsigned int ni, result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
[self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:cursor];
|
1998-03-06 18:13:53 +00:00
|
|
|
|
result = NSSwapBigIntToHost (ni);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
return result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (int)deserializeIntAtIndex:(unsigned int)index
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
unsigned int ni, result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
[self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:&index];
|
1998-03-06 18:13:53 +00:00
|
|
|
|
result = NSSwapBigIntToHost (ni);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
return result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (void)deserializeInts:(int*)intBuffer
|
1997-09-29 14:39:53 +00:00
|
|
|
|
count:(unsigned int)numInts
|
|
|
|
|
atCursor:(unsigned int*)cursor
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
[self deserializeBytes:&intBuffer
|
|
|
|
|
length:numInts * sizeof(unsigned int)
|
|
|
|
|
atCursor:cursor];
|
|
|
|
|
for (i = 0; i < numInts; i++)
|
1998-03-06 18:13:53 +00:00
|
|
|
|
intBuffer[i] = NSSwapBigIntToHost (intBuffer[i]);
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (void)deserializeInts:(int*)intBuffer
|
1997-09-29 14:39:53 +00:00
|
|
|
|
count:(unsigned int)numInts
|
|
|
|
|
atIndex:(unsigned int)index
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
[self deserializeBytes:&intBuffer
|
|
|
|
|
length:numInts * sizeof(int)
|
|
|
|
|
atCursor:&index];
|
|
|
|
|
for (i = 0; i < numInts; i++)
|
1998-03-06 18:13:53 +00:00
|
|
|
|
intBuffer[i] = NSSwapBigIntToHost (intBuffer[i]);
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) copyWithZone: (NSZone*)zone
|
|
|
|
|
{
|
1998-03-12 14:21:20 +00:00
|
|
|
|
if (NSShouldRetainWithZone(self, zone) &&
|
|
|
|
|
[self isKindOfClass: [NSMutableData class]] == NO)
|
|
|
|
|
return [self retain];
|
|
|
|
|
else
|
|
|
|
|
return [[NSDataMalloc allocWithZone: zone]
|
|
|
|
|
initWithBytes: [self bytes] length: [self length]];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) mutableCopyWithZone: (NSZone*)zone
|
|
|
|
|
{
|
1998-03-12 14:21:20 +00:00
|
|
|
|
return [[NSMutableDataMalloc allocWithZone: zone]
|
|
|
|
|
initWithBytes: [self bytes] length: [self length]];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (void) encodeWithCoder:(NSCoder*)coder
|
|
|
|
|
{
|
|
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithCoder:(NSCoder*)coder
|
|
|
|
|
{
|
|
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-09 02:20:37 +00:00
|
|
|
|
@end
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@implementation NSData (GNUstepExtensions)
|
|
|
|
|
+ (id) dataWithShmID: (int)anID length: (unsigned)length
|
|
|
|
|
{
|
|
|
|
|
#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]
|
1997-11-12 15:37:27 +00:00
|
|
|
|
autorelease];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
+ (id) dataWithStaticBytes: (const void*)bytes length: (unsigned)length
|
|
|
|
|
{
|
|
|
|
|
return [[[NSDataStatic alloc] initWithBytesNoCopy:(void*)bytes length:length]
|
|
|
|
|
autorelease];
|
|
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
- (id) initWithBytesNoCopy: (void*)bytes
|
|
|
|
|
length: (unsigned)length
|
|
|
|
|
fromZone: (NSZone*)zone
|
|
|
|
|
{
|
|
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
|
}
|
|
|
|
|
|
1998-02-05 22:06:20 +00:00
|
|
|
|
- (void*) relinquishAllocatedBytes
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
return 0; /* No data from NSZoneMalloc - return nul pointer */
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@end
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
1995-04-17 20:40:59 +00:00
|
|
|
|
@implementation NSMutableData
|
1997-09-29 14:39:53 +00:00
|
|
|
|
+ (NSData*) allocWithZone: (NSZone*)z
|
|
|
|
|
{
|
|
|
|
|
return (NSData*)NSAllocateObject([NSMutableDataMalloc class], 0, z);
|
|
|
|
|
}
|
|
|
|
|
|
1998-06-24 21:53:49 +00:00
|
|
|
|
+ (id) data
|
|
|
|
|
{
|
|
|
|
|
return [[[NSMutableDataMalloc alloc] initWithCapacity: 0] autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
+ (id) dataWithBytes: (const void*)bytes
|
|
|
|
|
length: (unsigned int)length
|
|
|
|
|
{
|
|
|
|
|
return [[[NSMutableDataMalloc alloc] initWithBytes:bytes length:length]
|
|
|
|
|
autorelease];
|
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
+ (id) dataWithBytesNoCopy: (void*)bytes
|
|
|
|
|
length: (unsigned int)length
|
1995-08-23 15:36:59 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [[[NSMutableDataMalloc alloc] initWithBytesNoCopy:bytes length:length]
|
|
|
|
|
autorelease];
|
1995-08-23 15:36:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-04-17 20:40:59 +00:00
|
|
|
|
+ (id) dataWithCapacity: (unsigned int)numBytes
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
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]
|
1995-04-17 20:40:59 +00:00
|
|
|
|
autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
1998-01-19 15:20:15 +00:00
|
|
|
|
+ (id) dataWithData: (NSData*)data
|
|
|
|
|
{
|
|
|
|
|
return [[[NSMutableDataMalloc alloc] initWithBytes: [data bytes]
|
|
|
|
|
length: [data length]]
|
|
|
|
|
autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-17 20:40:59 +00:00
|
|
|
|
+ (id) dataWithLength: (unsigned int)length
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [[[NSMutableDataMalloc alloc] initWithLength:length]
|
1995-04-17 20:40:59 +00:00
|
|
|
|
autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (const void*) bytes
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [self mutableBytes];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (id) initWithCapacity: (unsigned int)capacity
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1995-08-02 14:51:26 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithLength: (unsigned int)length
|
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
|
return nil;
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Adjusting Capacity
|
|
|
|
|
|
|
|
|
|
- (void) increaseLengthBy: (unsigned int)extraLength
|
|
|
|
|
{
|
|
|
|
|
[self setLength:[self length]+extraLength];
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (void) setLength: (unsigned)size
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void*) mutableBytes
|
|
|
|
|
{
|
1996-02-22 16:05:12 +00:00
|
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Appending Data
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (void) appendBytes: (const void*)aBuffer
|
|
|
|
|
length: (unsigned int)bufferSize
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1997-09-29 14:39:53 +00:00
|
|
|
|
unsigned oldLength = [self length];
|
|
|
|
|
void* buffer;
|
|
|
|
|
|
|
|
|
|
[self setLength: oldLength + bufferSize];
|
|
|
|
|
buffer = [self mutableBytes];
|
|
|
|
|
memcpy(buffer + oldLength, aBuffer, bufferSize);
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) appendData: (NSData*)other
|
|
|
|
|
{
|
|
|
|
|
[self appendBytes:[other bytes]
|
1997-09-29 14:39:53 +00:00
|
|
|
|
length:[other length]];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Modifying Data
|
|
|
|
|
|
|
|
|
|
- (void) replaceBytesInRange: (NSRange)aRange
|
|
|
|
|
withBytes: (const void*)bytes
|
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
auto int size;
|
|
|
|
|
|
|
|
|
|
// Check for 'out of range' errors. This code assumes that the
|
|
|
|
|
// NSRange location and length types will remain unsigned (hence
|
|
|
|
|
// the lack of a less-than-zero check).
|
|
|
|
|
size = [self length];
|
1997-10-16 23:56:27 +00:00
|
|
|
|
if (aRange.location > size ||
|
|
|
|
|
aRange.length > size ||
|
1997-09-01 21:59:51 +00:00
|
|
|
|
NSMaxRange( aRange ) > size)
|
|
|
|
|
{
|
|
|
|
|
// Raise an exception.
|
|
|
|
|
[NSException raise : NSRangeException
|
|
|
|
|
format : @"Range: (%u, %u) Size: %d",
|
|
|
|
|
aRange.location,
|
|
|
|
|
aRange.length,
|
|
|
|
|
size];
|
|
|
|
|
}
|
1995-04-17 21:31:59 +00:00
|
|
|
|
memcpy([self mutableBytes] + aRange.location, bytes, aRange.length);
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) resetBytesInRange: (NSRange)aRange
|
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
auto int size;
|
|
|
|
|
|
|
|
|
|
// Check for 'out of range' errors. This code assumes that the
|
|
|
|
|
// NSRange location and length types will remain unsigned (hence
|
|
|
|
|
// the lack of a less-than-zero check).
|
|
|
|
|
size = [self length];
|
1997-10-16 23:56:27 +00:00
|
|
|
|
if (aRange.location > size ||
|
|
|
|
|
aRange.length > size ||
|
1997-09-01 21:59:51 +00:00
|
|
|
|
NSMaxRange( aRange ) > size)
|
|
|
|
|
{
|
|
|
|
|
// Raise an exception.
|
|
|
|
|
[NSException raise : NSRangeException
|
|
|
|
|
format : @"Range: (%u, %u) Size: %d",
|
|
|
|
|
aRange.location,
|
|
|
|
|
aRange.length,
|
|
|
|
|
size];
|
|
|
|
|
}
|
1996-03-26 00:28:20 +00:00
|
|
|
|
memset((char*)[self bytes] + aRange.location, 0, aRange.length);
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-01-19 15:20:15 +00:00
|
|
|
|
- (void) setData: (NSData*)data
|
|
|
|
|
{
|
|
|
|
|
NSRange r = NSMakeRange(0, [data length]);
|
|
|
|
|
|
|
|
|
|
[self setCapacity: [data length]];
|
|
|
|
|
[self replaceBytesInRange: r withBytes: [data bytes]];
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-17 20:40:59 +00:00
|
|
|
|
// Serializing Data
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (void)serializeAlignedBytesLength:(unsigned int)length
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)serializeDataAt:(const void*)data
|
|
|
|
|
ofObjCType:(const char*)type
|
|
|
|
|
context:(id <NSObjCTypeSerializationCallBack>)callback
|
|
|
|
|
{
|
|
|
|
|
if(!data || !type)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
switch(*type) {
|
|
|
|
|
case _C_ID: {
|
|
|
|
|
[callback serializeObjectAt:(id*)data
|
|
|
|
|
ofObjCType:type
|
|
|
|
|
intoData: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(type + 1);
|
|
|
|
|
const char* itemType = type;
|
|
|
|
|
|
|
|
|
|
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(*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
|
|
|
|
while(1) {
|
|
|
|
|
[self serializeDataAt:((char*)data) + offset
|
|
|
|
|
ofObjCType:type
|
|
|
|
|
context:callback];
|
|
|
|
|
offset += objc_sizeof_type(type);
|
|
|
|
|
type = objc_skip_typespec(type);
|
|
|
|
|
if(*type != _C_STRUCT_E) {
|
|
|
|
|
align = objc_alignof_type(type);
|
|
|
|
|
if((rem = offset % align))
|
|
|
|
|
offset += align - rem;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_PTR:
|
|
|
|
|
[self serializeDataAt:*(char**)data
|
|
|
|
|
ofObjCType:++type context:callback];
|
|
|
|
|
break;
|
|
|
|
|
case _C_CHR:
|
|
|
|
|
case _C_UCHR:
|
|
|
|
|
[self appendBytes:data length:sizeof(unsigned char)];
|
|
|
|
|
break;
|
|
|
|
|
case _C_SHT:
|
|
|
|
|
case _C_USHT: {
|
1998-03-06 18:13:53 +00:00
|
|
|
|
unsigned short ns = NSSwapHostShortToBig (*(unsigned short*)data);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
[self appendBytes:&ns length:sizeof(unsigned short)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_INT:
|
|
|
|
|
case _C_UINT: {
|
1998-03-06 18:13:53 +00:00
|
|
|
|
unsigned int ni = NSSwapHostIntToBig (*(unsigned int*)data);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
[self appendBytes:&ni length:sizeof(unsigned int)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_LNG:
|
|
|
|
|
case _C_ULNG: {
|
1998-03-06 18:13:53 +00:00
|
|
|
|
unsigned long nl = NSSwapHostLongToBig (*(unsigned long*)data);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
[self appendBytes:&nl length:sizeof(unsigned long)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_FLT: {
|
1998-03-06 18:13:53 +00:00
|
|
|
|
NSSwappedFloat nf = NSSwapHostFloatToBig (*(float*)data);
|
|
|
|
|
[self appendBytes:&nf length:sizeof(NSSwappedFloat)];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_DBL: {
|
1998-03-06 18:13:53 +00:00
|
|
|
|
NSSwappedDouble nd = NSSwapHostDoubleToBig (*(double*)data);
|
|
|
|
|
[self appendBytes:&nd length:sizeof(NSSwappedDouble)];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
[NSException raise:NSGenericException
|
|
|
|
|
format:@"Unknown type to deserialize - '%s'", type];
|
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (void)serializeInt:(int)value
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1998-03-06 18:13:53 +00:00
|
|
|
|
unsigned int ni = NSSwapHostIntToBig (value);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
[self appendBytes:&ni length:sizeof(unsigned int)];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (void)serializeInt:(int)value atIndex:(unsigned int)index
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1998-03-06 18:13:53 +00:00
|
|
|
|
unsigned int ni = NSSwapHostIntToBig (value);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
NSRange range = { index, sizeof(int) };
|
|
|
|
|
[self replaceBytesInRange:range withBytes:&ni];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (void)serializeInts:(int*)intBuffer count:(unsigned int)numInts
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
unsigned i;
|
|
|
|
|
SEL selector = @selector (serializeInt:);
|
|
|
|
|
IMP imp = [self methodForSelector:selector];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
for (i = 0; i < numInts; i++)
|
|
|
|
|
(*imp)(self, selector, intBuffer[i]);
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
- (void)serializeInts:(int*)intBuffer
|
|
|
|
|
count:(unsigned int)numInts
|
|
|
|
|
atIndex:(unsigned int)index
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
unsigned i;
|
|
|
|
|
SEL selector = @selector (serializeInt:atIndex:);
|
|
|
|
|
IMP imp = [self methodForSelector:selector];
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < numInts; i++)
|
|
|
|
|
(*imp)(self, selector, intBuffer[i], index++);
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@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];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
|
|
|
|
if (bytes)
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZoneFree(zone, bytes);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = 0;
|
|
|
|
|
length = 0;
|
|
|
|
|
}
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
[aCoder encodeValueOfObjCType: @encode(unsigned long) at: &length];
|
|
|
|
|
[aCoder encodeArrayOfObjCType: @encode(unsigned char) count:length at: bytes];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
return [self initWithBytesNoCopy: 0 length: 0 fromZone: [self zone]];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithBytes: (const void*)aBuffer length: (unsigned int)bufferSize
|
|
|
|
|
{
|
|
|
|
|
void* tmp = 0;
|
|
|
|
|
|
|
|
|
|
if (aBuffer != 0 && bufferSize > 0)
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
zone = [self zone];
|
|
|
|
|
tmp = NSZoneMalloc(zone, bufferSize);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
if (tmp == 0)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSDataMalloc -initWithBytes:length:] unable to allocate %lu bytes", bufferSize);
|
|
|
|
|
[self dealloc];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
memcpy(tmp, aBuffer, bufferSize);
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-15 05:03:16 +00:00
|
|
|
|
self = [self initWithBytesNoCopy:tmp length:bufferSize fromZone: zone];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
|
|
|
|
length: (unsigned int)bufferSize
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZone *z = NSZoneFromPointer(aBuffer);
|
|
|
|
|
|
|
|
|
|
return [self initWithBytesNoCopy: aBuffer length: bufferSize fromZone: z];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
|
|
|
|
length: (unsigned)bufferSize
|
|
|
|
|
fromZone: (NSZone*)aZone
|
|
|
|
|
{
|
|
|
|
|
if (aZone == 0)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSData *data;
|
|
|
|
|
|
|
|
|
|
data = [[NSDataStatic alloc] initWithBytesNoCopy: aBuffer
|
|
|
|
|
length: bufferSize];
|
|
|
|
|
[self dealloc];
|
|
|
|
|
return data;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1998-10-15 05:03:16 +00:00
|
|
|
|
|
|
|
|
|
zone = aZone;
|
|
|
|
|
bytes = aBuffer;
|
|
|
|
|
if (bytes)
|
|
|
|
|
length = bufferSize;
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
|
|
|
|
unsigned int l;
|
|
|
|
|
void* b;
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
zone = [self zone];
|
|
|
|
|
|
|
|
|
|
[aCoder decodeValueOfObjCType: @encode(unsigned long) at: &l];
|
|
|
|
|
if (l)
|
1997-12-11 19:09:56 +00:00
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
b = NSZoneMalloc(zone, l);
|
|
|
|
|
if (b == 0)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSDataMalloc -initWithCoder:] unable to get %lu bytes", l);
|
|
|
|
|
[self dealloc];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
[aCoder decodeArrayOfObjCType: @encode(unsigned char) count: l at: b];
|
1997-12-11 19:09:56 +00:00
|
|
|
|
}
|
1998-10-15 05:03:16 +00:00
|
|
|
|
else
|
|
|
|
|
b = 0;
|
|
|
|
|
return [self initWithBytesNoCopy: b length: l fromZone: zone];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithContentsOfFile: (NSString *)path
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
zone = [self zone];
|
|
|
|
|
if (readContentsOfFile(path, &bytes, &length, zone) == NO)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
[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)
|
1998-10-15 05:03:16 +00:00
|
|
|
|
return [self initWithBytesNoCopy: 0 length: 0 fromZone: [self zone]];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
1998-02-05 22:06:20 +00:00
|
|
|
|
- (void*) relinquishAllocatedBytes
|
|
|
|
|
{
|
|
|
|
|
void *buf = bytes;
|
|
|
|
|
|
|
|
|
|
bytes = 0;
|
|
|
|
|
length = 0;
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@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;
|
1998-02-03 14:20:00 +00:00
|
|
|
|
char thePath[BUFSIZ*2];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
1998-02-03 14:20:00 +00:00
|
|
|
|
if ([path getFileSystemRepresentation: thePath
|
|
|
|
|
maxLength: sizeof(thePath)-1] == NO)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Open (%s) attempt failed - bad path", thePath);
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
fd = open(thePath, O_RDONLY);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
if (fd < 0)
|
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"[NSDataMappedFile -initWithContentsOfMappedFile:] unable to open %s - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
[self dealloc];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
/* Find size of file to be mapped. */
|
|
|
|
|
length = lseek(fd, 0, SEEK_END);
|
|
|
|
|
if (length < 0)
|
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"[NSDataMappedFile -initWithContentsOfMappedFile:] unable to seek to eof %s - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
close(fd);
|
|
|
|
|
[self dealloc];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
/* Position at start of file. */
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) != 0)
|
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"[NSDataMappedFile -initWithContentsOfMappedFile:] unable to seek to sof %s - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
close(fd);
|
|
|
|
|
[self dealloc];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
bytes = mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
|
|
|
|
|
if (bytes == MAP_FAILED)
|
|
|
|
|
{
|
1998-02-03 14:20:00 +00:00
|
|
|
|
NSLog(@"[NSDataMappedFile -initWithContentsOfMappedFile:] mapping failed for %s - %s", thePath, strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
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)
|
|
|
|
|
{
|
1997-10-28 14:34:49 +00:00
|
|
|
|
struct shmid_ds buf;
|
|
|
|
|
|
|
|
|
|
if (shmctl(shmid, IPC_STAT, &buf) < 0)
|
|
|
|
|
NSLog(@"[NSDataShared -dealloc] shared memory control failed - %s",
|
|
|
|
|
strerror(errno));
|
|
|
|
|
else if (buf.shm_nattch == 1)
|
|
|
|
|
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
|
|
|
|
|
NSLog(@"[NSDataShared -dealloc] shared memory delete failed - %s",
|
|
|
|
|
strerror(errno));
|
|
|
|
|
if (shmdt(bytes) < 0)
|
|
|
|
|
NSLog(@"[NSDataShared -dealloc] shared memory detach failed - %s",
|
|
|
|
|
strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = 0;
|
|
|
|
|
length = 0;
|
|
|
|
|
shmid = -1;
|
|
|
|
|
}
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithBytes: (const void*)aBuffer length: (unsigned)bufferSize
|
|
|
|
|
{
|
|
|
|
|
struct shmid_ds buf;
|
|
|
|
|
|
|
|
|
|
shmid = -1;
|
|
|
|
|
if (aBuffer && bufferSize)
|
|
|
|
|
{
|
1997-10-28 14:34:49 +00:00
|
|
|
|
shmid = shmget(IPC_PRIVATE, bufferSize, IPC_CREAT|VM_RDONLY);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
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);
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
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) initWithBytesNoCopy: (void*)aBuffer
|
1998-10-15 05:03:16 +00:00
|
|
|
|
length: (unsigned)bufferSize
|
|
|
|
|
fromZone: (NSZone*)aZone
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
bytes = aBuffer;
|
|
|
|
|
length = bufferSize;
|
|
|
|
|
return self;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@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];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
|
|
|
|
if (bytes)
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZoneFree(zone, bytes);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = 0;
|
|
|
|
|
length = 0;
|
|
|
|
|
capacity = 0;
|
|
|
|
|
}
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
[aCoder encodeValueOfObjCType: @encode(unsigned long) at: &length];
|
|
|
|
|
[aCoder encodeArrayOfObjCType: @encode(unsigned char) count:length at: bytes];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (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
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZone *aZone = NSZoneFromPointer(aBuffer);
|
|
|
|
|
return [self initWithBytesNoCopy: aBuffer length: bufferSize fromZone: aZone];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* THIS IS THE DESIGNATED INITIALISER
|
|
|
|
|
*/
|
1998-10-15 05:03:16 +00:00
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
|
|
|
|
length: (unsigned)bufferSize
|
|
|
|
|
fromZone: (NSZone*)aZone
|
|
|
|
|
{
|
|
|
|
|
if (aZone == 0)
|
|
|
|
|
{
|
|
|
|
|
self = [self initWithBytes: aBuffer length: bufferSize];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
self = [self initWithCapacity: bufferSize];
|
|
|
|
|
if (self)
|
|
|
|
|
[self setLength: bufferSize];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zone = aZone;
|
|
|
|
|
bytes = aBuffer;
|
|
|
|
|
length = bufferSize;
|
|
|
|
|
capacity = bufferSize;
|
|
|
|
|
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (id) initWithCapacity: (unsigned)size
|
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
zone = [self zone];
|
|
|
|
|
if (size)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
bytes = NSZoneMalloc(zone, size);
|
|
|
|
|
if (bytes == 0)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSMutableDataMalloc -initWithCapacity:] out of memory for %u bytes - %s", size, strerror(errno));
|
|
|
|
|
[self dealloc];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1998-10-15 05:03:16 +00:00
|
|
|
|
capacity = size;
|
|
|
|
|
length = 0;
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
|
|
|
|
unsigned int l;
|
|
|
|
|
void* b;
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
[aCoder decodeValueOfObjCType: @encode(unsigned long) at: &l];
|
|
|
|
|
if (l)
|
1997-12-11 19:09:56 +00:00
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
[self initWithCapacity: l];
|
|
|
|
|
if (bytes == 0)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSMutableDataMalloc -initWithCoder:] unable to allocate %lu bytes", l);
|
|
|
|
|
[self dealloc];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
[aCoder decodeArrayOfObjCType: @encode(unsigned char) count: l at: bytes];
|
|
|
|
|
length = l;
|
1997-12-11 19:09:56 +00:00
|
|
|
|
}
|
1998-10-15 05:03:16 +00:00
|
|
|
|
return self;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (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];
|
1998-10-15 05:03:16 +00:00
|
|
|
|
if (readContentsOfFile(path, &bytes, &length, zone) == NO)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
[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) setCapacity: (unsigned int)size
|
|
|
|
|
{
|
|
|
|
|
if (size != capacity)
|
|
|
|
|
{
|
1997-10-17 13:35:52 +00:00
|
|
|
|
void* tmp;
|
|
|
|
|
|
|
|
|
|
if (bytes)
|
1998-10-15 05:03:16 +00:00
|
|
|
|
tmp = NSZoneRealloc(zone, bytes, size);
|
1997-10-17 13:35:52 +00:00
|
|
|
|
else
|
1998-10-15 05:03:16 +00:00
|
|
|
|
tmp = NSZoneMalloc(zone, size);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
1998-02-05 22:06:20 +00:00
|
|
|
|
- (void*) relinquishAllocatedBytes
|
|
|
|
|
{
|
|
|
|
|
capacity = 0;
|
|
|
|
|
return [super relinquishAllocatedBytes];
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_SHMCTL
|
|
|
|
|
@implementation NSMutableDataShared
|
|
|
|
|
+ (NSData*) allocWithZone: (NSZone*)z
|
|
|
|
|
{
|
|
|
|
|
return (NSData*)NSAllocateObject([NSMutableDataShared class], 0, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
|
|
|
|
if (bytes)
|
|
|
|
|
{
|
1997-10-28 14:34:49 +00:00
|
|
|
|
struct shmid_ds buf;
|
|
|
|
|
|
|
|
|
|
if (shmctl(shmid, IPC_STAT, &buf) < 0)
|
|
|
|
|
NSLog(@"[NSMutableDataShared -dealloc] shared memory control failed - %s", strerror(errno));
|
|
|
|
|
else if (buf.shm_nattch == 1)
|
|
|
|
|
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
|
|
|
|
|
NSLog(@"[NSMutableDataShared -dealloc] shared memory delete failed - %s", strerror(errno));
|
|
|
|
|
if (shmdt(bytes) < 0)
|
|
|
|
|
NSLog(@"[NSMutableDataShared -dealloc] shared memory detach failed - %s", strerror(errno));
|
1997-09-29 14:39:53 +00:00
|
|
|
|
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;
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
shmid = shmget(IPC_PRIVATE, bufferSize, IPC_CREAT|VM_ACCESS);
|
|
|
|
|
if (shmid == -1) /* Created memory? */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSLog(@"[NSMutableDataShared -initWithCapacity:] shared memory get failed for %u - %s", bufferSize, strerror(errno));
|
|
|
|
|
[self dealloc];
|
|
|
|
|
self = [NSMutableDataMalloc alloc];
|
|
|
|
|
return [self initWithCapacity: bufferSize];
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
bytes = shmat(shmid, 0, 0);
|
|
|
|
|
e = errno;
|
|
|
|
|
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];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1998-10-15 05:03:16 +00:00
|
|
|
|
length = 0;
|
|
|
|
|
capacity = bufferSize;
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithShmID: (int)anId length: (unsigned)bufferSize
|
|
|
|
|
{
|
|
|
|
|
struct shmid_ds buf;
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
shmid = anId;
|
|
|
|
|
if (shmctl(shmid, IPC_STAT, &buf) < 0)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-10-15 05:03:16 +00:00
|
|
|
|
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;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1998-10-15 05:03:16 +00:00
|
|
|
|
length = bufferSize;
|
|
|
|
|
capacity = length;
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
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 ((int)tmp == -1) /* Attached memory? */
|
|
|
|
|
[NSException raise:NSMallocException
|
|
|
|
|
format:@"Unable to attach to shared memory segment."];
|
|
|
|
|
memcpy(tmp, bytes, length);
|
|
|
|
|
if (bytes)
|
1997-10-28 14:34:49 +00:00
|
|
|
|
{
|
|
|
|
|
struct shmid_ds buf;
|
|
|
|
|
|
|
|
|
|
if (shmctl(shmid, IPC_STAT, &buf) < 0)
|
|
|
|
|
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory control failed - %s", strerror(errno));
|
|
|
|
|
else if (buf.shm_nattch == 1)
|
|
|
|
|
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
|
|
|
|
|
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory delete failed - %s", strerror(errno));
|
|
|
|
|
if (shmdt(bytes) < 0) /* Detach memory. */
|
|
|
|
|
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory detach failed - %s", strerror(errno));
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = tmp;
|
|
|
|
|
shmid = newid;
|
|
|
|
|
capacity = size;
|
|
|
|
|
}
|
|
|
|
|
if (size < length)
|
|
|
|
|
length = size;
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (int) shmID
|
|
|
|
|
{
|
|
|
|
|
return shmid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
#endif /* HAVE_SHMCTL */
|
|
|
|
|
|