2002-08-20 10:22:05 +00:00
|
|
|
|
/**
|
|
|
|
|
Copyright (C) 1995, 1996, 1997, 2000, 2002 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +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
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
|
This file is part of the GNUstep Base Library.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1995-04-09 02:20:37 +00:00
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
1995-04-09 02:20:37 +00:00
|
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1995-04-09 02:20:37 +00:00
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
Library General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
1995-04-09 02:20:37 +00:00
|
|
|
|
License along with this library; if not, write to the Free
|
2006-06-04 06:42:10 +00:00
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
|
Boston, MA 02111 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
|
|
|
|
|
<title>NSData class reference</title>
|
|
|
|
|
$Date$ $Revision$
|
1995-04-09 02:20:37 +00:00
|
|
|
|
*/
|
|
|
|
|
|
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
|
1998-10-21 11:56:58 +00:00
|
|
|
|
* never shrinks the allocated buffer capacity
|
1997-09-29 14:39:53 +00:00
|
|
|
|
* [-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.
|
1998-10-21 11:56:58 +00:00
|
|
|
|
* NSDataStatic Concrete class static buffers.
|
2002-08-27 12:26:17 +00:00
|
|
|
|
* NSDataEmpty Concrete class static buffers.
|
1998-10-21 11:56:58 +00:00
|
|
|
|
* NSDataMalloc Concrete class.
|
|
|
|
|
* NSDataMappedFile Memory mapped files.
|
|
|
|
|
* NSDataShared Extension for shared memory.
|
2009-04-15 08:03:19 +00:00
|
|
|
|
* NSDataFinalized For GC of non-GC data.
|
1997-09-29 14:39:53 +00:00
|
|
|
|
* NSMutableData Abstract base class.
|
|
|
|
|
* NSMutableDataMalloc Concrete class.
|
|
|
|
|
* NSMutableDataShared Extension for shared memory.
|
2009-04-15 08:03:19 +00:00
|
|
|
|
* NSDataMutableFinalized For GC of non-GC data.
|
1997-09-29 14:39:53 +00:00
|
|
|
|
*
|
1998-10-21 11:56:58 +00:00
|
|
|
|
* NSMutableDataMalloc MUST share it's initial instance variable layout
|
|
|
|
|
* with NSDataMalloc so that it can use the 'behavior' code to inherit
|
|
|
|
|
* methods from NSDataMalloc.
|
|
|
|
|
*
|
1997-09-29 14:39:53 +00:00
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2010-02-19 08:12:46 +00:00
|
|
|
|
#import "common.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
|
#import "GNUstepBase/GSObjCRuntime.h"
|
|
|
|
|
#import "Foundation/NSByteOrder.h"
|
|
|
|
|
#import "Foundation/NSCoder.h"
|
|
|
|
|
#import "Foundation/NSData.h"
|
|
|
|
|
#import "Foundation/NSException.h"
|
|
|
|
|
#import "Foundation/NSFileManager.h"
|
|
|
|
|
#import "Foundation/NSPathUtilities.h"
|
|
|
|
|
#import "Foundation/NSRange.h"
|
|
|
|
|
#import "Foundation/NSURL.h"
|
|
|
|
|
#import "Foundation/NSValue.h"
|
|
|
|
|
#import "GSPrivate.h"
|
|
|
|
|
#import "GNUstepBase/NSObject+GNUstepBase.h"
|
2001-05-29 02:38:22 +00:00
|
|
|
|
#include <stdio.h>
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_UNISTD_H
|
1997-09-01 21:59:51 +00:00
|
|
|
|
#include <unistd.h> /* SEEK_* on SunOS 4 */
|
2002-02-20 06:42:05 +00:00
|
|
|
|
#endif
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_MMAP
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#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
|
|
|
|
|
2001-11-01 15:42:42 +00:00
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SHMCTL
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#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;
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
@class NSDataFinalized;
|
2009-04-15 08:03:19 +00:00
|
|
|
|
@class NSMutableDataFinalized;
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#endif
|
1995-07-03 22:10:49 +00:00
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
/*
|
|
|
|
|
* Some static variables to cache classes and methods for quick access -
|
|
|
|
|
* these are set up at process startup or in [NSData +initialize]
|
|
|
|
|
*/
|
2000-07-03 11:47:17 +00:00
|
|
|
|
static Class dataStatic;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
static Class dataMalloc;
|
|
|
|
|
static Class mutableDataMalloc;
|
2000-08-07 22:00:31 +00:00
|
|
|
|
static Class NSDataAbstract;
|
|
|
|
|
static Class NSMutableDataAbstract;
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
static Class dataFinalized;
|
|
|
|
|
static Class mutableDataFinalized;
|
|
|
|
|
#endif
|
2000-10-30 18:00:27 +00:00
|
|
|
|
static SEL appendSel;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
static IMP appendImp;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
|
|
|
|
static BOOL
|
2001-12-17 14:31:42 +00:00
|
|
|
|
readContentsOfFile(NSString* path, void** buf, unsigned int* len, NSZone* zone)
|
1995-07-03 22:10:49 +00:00
|
|
|
|
{
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2005-06-04 07:22:51 +00:00
|
|
|
|
const unichar *thePath = 0;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#else
|
2005-06-04 07:22:51 +00:00
|
|
|
|
const char *thePath = 0;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#endif
|
2005-03-18 15:26:18 +00:00
|
|
|
|
FILE *theFile = 0;
|
|
|
|
|
void *tmp = 0;
|
|
|
|
|
int c;
|
|
|
|
|
long fileLength;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2005-06-04 07:22:51 +00:00
|
|
|
|
thePath = (const unichar*)[path fileSystemRepresentation];
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#else
|
2005-06-04 07:22:51 +00:00
|
|
|
|
thePath = [path fileSystemRepresentation];
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#endif
|
2005-06-04 07:22:51 +00:00
|
|
|
|
if (thePath == 0)
|
2005-03-18 15:26:18 +00:00
|
|
|
|
{
|
2005-06-04 07:22:51 +00:00
|
|
|
|
NSWarnFLog(@"Open (%@) attempt failed - bad path", path);
|
2005-03-18 15:26:18 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2005-03-18 15:26:18 +00:00
|
|
|
|
theFile = _wfopen(thePath, L"rb");
|
|
|
|
|
#else
|
|
|
|
|
theFile = fopen(thePath, "rb");
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-06-04 07:22:51 +00:00
|
|
|
|
if (theFile == 0) /* We failed to open the file. */
|
2005-03-18 15:26:18 +00:00
|
|
|
|
{
|
2007-05-29 09:07:47 +00:00
|
|
|
|
NSDebugFLog(@"Open (%@) attempt failed - %@", path, [NSError _last]);
|
2005-03-18 15:26:18 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
2010-05-29 08:05:03 +00:00
|
|
|
|
|
2005-03-18 15:26:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* Seek to the end of the file.
|
|
|
|
|
*/
|
|
|
|
|
c = fseek(theFile, 0L, SEEK_END);
|
|
|
|
|
if (c != 0)
|
|
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSWarnFLog(@"Seek to end of file (%@) failed - %@", path,
|
2006-10-20 10:56:27 +00:00
|
|
|
|
[NSError _last]);
|
2005-03-18 15:26:18 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2005-03-18 15:26:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* Determine the length of the file (having seeked to the end of the
|
|
|
|
|
* file) by calling ftell().
|
|
|
|
|
*/
|
|
|
|
|
fileLength = ftell(theFile);
|
|
|
|
|
if (fileLength == -1)
|
|
|
|
|
{
|
2006-10-20 10:56:27 +00:00
|
|
|
|
NSWarnFLog(@"Ftell on %@ failed - %@", path, [NSError _last]);
|
2005-03-18 15:26:18 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2005-03-18 15:26:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* Rewind the file pointer to the beginning, preparing to read in
|
|
|
|
|
* the file.
|
|
|
|
|
*/
|
|
|
|
|
c = fseek(theFile, 0L, SEEK_SET);
|
|
|
|
|
if (c != 0)
|
|
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSWarnFLog(@"Fseek to start of file (%@) failed - %@", path,
|
2006-10-20 10:56:27 +00:00
|
|
|
|
[NSError _last]);
|
2005-03-18 15:26:18 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
2010-05-29 08:05:03 +00:00
|
|
|
|
|
|
|
|
|
clearerr(theFile);
|
2005-03-18 15:26:18 +00:00
|
|
|
|
if (fileLength == 0)
|
|
|
|
|
{
|
|
|
|
|
unsigned char buf[BUFSIZ];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Special case ... a file of length zero may be a named pipe or some
|
|
|
|
|
* file in the /proc filesystem, which will return us data if we read
|
|
|
|
|
* from it ... so we try reading as much as we can.
|
|
|
|
|
*/
|
|
|
|
|
while ((c = fread(buf, 1, BUFSIZ, theFile)) != 0)
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
if (tmp == 0)
|
|
|
|
|
{
|
|
|
|
|
tmp = NSAllocateCollectable(c, 0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tmp = NSReallocateCollectable(tmp, fileLength + c, 0);
|
|
|
|
|
}
|
|
|
|
|
#else
|
2005-03-18 15:26:18 +00:00
|
|
|
|
if (tmp == 0)
|
|
|
|
|
{
|
|
|
|
|
tmp = NSZoneMalloc(zone, c);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tmp = NSZoneRealloc(zone, tmp, fileLength + c);
|
|
|
|
|
}
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#endif
|
2005-03-18 15:26:18 +00:00
|
|
|
|
if (tmp == 0)
|
|
|
|
|
{
|
2010-02-14 10:48:10 +00:00
|
|
|
|
NSLog(@"Malloc failed for file (%@) of length %ld - %@", path,
|
2006-10-20 10:56:27 +00:00
|
|
|
|
fileLength + c, [NSError _last]);
|
2005-03-18 15:26:18 +00:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
memcpy(tmp + fileLength, buf, c);
|
|
|
|
|
fileLength += c;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
}
|
2005-03-18 15:26:18 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2010-05-29 08:05:03 +00:00
|
|
|
|
long offset = 0;
|
|
|
|
|
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
tmp = NSAllocateCollectable(fileLength, 0);
|
|
|
|
|
#else
|
2005-03-18 15:26:18 +00:00
|
|
|
|
tmp = NSZoneMalloc(zone, fileLength);
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#endif
|
2005-03-18 15:26:18 +00:00
|
|
|
|
if (tmp == 0)
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
{
|
2010-02-14 10:48:10 +00:00
|
|
|
|
NSLog(@"Malloc failed for file (%@) of length %ld - %@", path,
|
2006-10-20 10:56:27 +00:00
|
|
|
|
fileLength, [NSError _last]);
|
2005-03-18 15:26:18 +00:00
|
|
|
|
goto failure;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
}
|
2005-03-18 15:26:18 +00:00
|
|
|
|
|
2010-05-29 08:05:03 +00:00
|
|
|
|
while (offset < fileLength
|
|
|
|
|
&& (c = fread(tmp + offset, 1, fileLength - offset, theFile)) != 0)
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
{
|
2010-05-29 08:05:03 +00:00
|
|
|
|
offset += c;
|
|
|
|
|
}
|
|
|
|
|
if (offset < fileLength)
|
|
|
|
|
{
|
|
|
|
|
fileLength = offset;
|
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
tmp = NSReallocateCollectable(tmp, fileLength, 0);
|
|
|
|
|
#else
|
|
|
|
|
tmp = NSZoneRealloc(zone, tmp, fileLength);
|
|
|
|
|
#endif
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
}
|
2005-03-18 15:26:18 +00:00
|
|
|
|
}
|
2010-05-29 08:05:03 +00:00
|
|
|
|
if (ferror(theFile))
|
|
|
|
|
{
|
|
|
|
|
NSWarnFLog(@"read of file (%@) contents failed - %@", path,
|
|
|
|
|
[NSError _last]);
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-18 15:26:18 +00:00
|
|
|
|
*buf = tmp;
|
|
|
|
|
*len = fileLength;
|
|
|
|
|
fclose(theFile);
|
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Just in case the failure action needs to be changed.
|
|
|
|
|
*/
|
1998-10-21 11:56:58 +00:00
|
|
|
|
failure:
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if !GS_WITH_GC
|
2005-03-18 15:26:18 +00:00
|
|
|
|
if (tmp != 0)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(zone, tmp);
|
|
|
|
|
}
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#endif
|
2005-03-18 15:26:18 +00:00
|
|
|
|
if (theFile != 0)
|
|
|
|
|
{
|
|
|
|
|
fclose(theFile);
|
|
|
|
|
}
|
|
|
|
|
return NO;
|
1995-07-03 22:10:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
/*
|
|
|
|
|
* NB, The start of the NSMutableDataMalloc instance variables must be
|
|
|
|
|
* identical to that of NSDataMalloc in order to inherit its methods.
|
|
|
|
|
*/
|
|
|
|
|
@interface NSDataStatic : NSData
|
1995-07-03 22:10:49 +00:00
|
|
|
|
{
|
2009-02-23 20:42:32 +00:00
|
|
|
|
NSUInteger length;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
void *bytes;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
@end
|
2009-04-15 08:03:19 +00:00
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
@interface NSDataEmpty: NSDataStatic
|
|
|
|
|
@end
|
1998-10-21 11:56:58 +00:00
|
|
|
|
|
|
|
|
|
@interface NSDataMalloc : NSDataStatic
|
2009-04-15 08:03:19 +00:00
|
|
|
|
@end
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@interface NSMutableDataMalloc : NSMutableData
|
1995-07-03 22:10:49 +00:00
|
|
|
|
{
|
2009-02-23 20:42:32 +00:00
|
|
|
|
NSUInteger length;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
void *bytes;
|
2009-04-15 08:03:19 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
BOOL owned;
|
|
|
|
|
#else
|
1998-10-15 05:03:16 +00:00
|
|
|
|
NSZone *zone;
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#endif
|
2009-02-23 20:42:32 +00:00
|
|
|
|
NSUInteger capacity;
|
|
|
|
|
NSUInteger growth;
|
1995-07-03 22:10:49 +00:00
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
/* Increase capacity to at least the specified minimum value. */
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) _grow: (NSUInteger)minimum;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@end
|
|
|
|
|
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
@interface NSDataFinalized : NSDataMalloc
|
|
|
|
|
@end
|
|
|
|
|
|
2009-04-15 08:03:19 +00:00
|
|
|
|
@interface NSMutableDataFinalized : NSMutableDataMalloc
|
|
|
|
|
@end
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#endif
|
2009-04-15 08:03:19 +00:00
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_MMAP
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@interface NSDataMappedFile : NSDataMalloc
|
|
|
|
|
@end
|
|
|
|
|
#endif
|
1995-07-03 22:10:49 +00:00
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SHMCTL
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@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
|
|
|
|
}
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithShmID: (int)anId length: (NSUInteger)bufferSize;
|
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 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
|
|
|
|
}
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithShmID: (int)anId length: (NSUInteger)bufferSize;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@end
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <p>Class for storing a byte array. Methods for initializing from memory a
|
|
|
|
|
* file, or the network are provided, as well as the ability to write to a
|
|
|
|
|
* file or the network. If desired, object can take over management of a
|
|
|
|
|
* pre-allocated buffer (with malloc or similar), free'ing it when deallocated.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>The data buffer at any given time has a <em>capacity</em>, which is the
|
|
|
|
|
* size of its allocated memory area, in bytes, and a <em>length</em>, which
|
|
|
|
|
* is the length of data it is currently storing.</p>
|
|
|
|
|
*/
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@implementation NSData
|
1998-10-20 14:40:05 +00:00
|
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (self == [NSData class])
|
|
|
|
|
{
|
2000-08-07 22:00:31 +00:00
|
|
|
|
NSDataAbstract = self;
|
|
|
|
|
NSMutableDataAbstract = [NSMutableData class];
|
2000-07-03 11:47:17 +00:00
|
|
|
|
dataStatic = [NSDataStatic class];
|
2009-04-15 08:03:19 +00:00
|
|
|
|
dataMalloc = [NSDataMalloc class];
|
1999-01-27 12:49:49 +00:00
|
|
|
|
mutableDataMalloc = [NSMutableDataMalloc class];
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
dataFinalized = [NSDataFinalized class];
|
2009-04-15 08:03:19 +00:00
|
|
|
|
mutableDataFinalized = [NSMutableDataFinalized class];
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#endif
|
2000-10-30 18:00:27 +00:00
|
|
|
|
appendSel = @selector(appendBytes:length:);
|
2000-06-27 16:18:02 +00:00
|
|
|
|
appendImp = [mutableDataMalloc instanceMethodForSelector: appendSel];
|
1998-10-20 14:40:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-14 10:38:22 +00:00
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
1995-08-23 15:36:59 +00:00
|
|
|
|
{
|
2000-08-07 22:00:31 +00:00
|
|
|
|
if (self == NSDataAbstract)
|
|
|
|
|
{
|
|
|
|
|
return NSAllocateObject(dataMalloc, 0, z);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return NSAllocateObject(self, 0, z);
|
|
|
|
|
}
|
1995-08-23 15:36:59 +00:00
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an empty data object.
|
|
|
|
|
*/
|
1995-04-09 02:20:37 +00:00
|
|
|
|
+ (id) data
|
|
|
|
|
{
|
2002-08-27 12:26:17 +00:00
|
|
|
|
static NSData *empty = nil;
|
1999-07-03 19:59:44 +00:00
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
if (empty == nil)
|
|
|
|
|
{
|
2009-04-15 08:03:19 +00:00
|
|
|
|
empty = [dataStatic allocWithZone: NSDefaultMallocZone()];
|
2002-08-27 12:26:17 +00:00
|
|
|
|
empty = [empty initWithBytesNoCopy: 0 length: 0 freeWhenDone: NO];
|
|
|
|
|
}
|
|
|
|
|
return empty;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an autoreleased data object containing data copied from bytes
|
|
|
|
|
* and with the specified length. Invokes -initWithBytes:length:
|
|
|
|
|
*/
|
1995-04-09 02:20:37 +00:00
|
|
|
|
+ (id) dataWithBytes: (const void*)bytes
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)length
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytes: bytes length: length];
|
|
|
|
|
return AUTORELEASE(d);
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an autoreleased data object encapsulating the data at bytes
|
|
|
|
|
* and with the specified length. Invokes
|
2005-02-22 11:22:44 +00:00
|
|
|
|
* -initWithBytesNoCopy:length:freeWhenDone: with YES
|
2002-10-04 09:08:09 +00:00
|
|
|
|
*/
|
1995-04-09 02:20:37 +00:00
|
|
|
|
+ (id) dataWithBytesNoCopy: (void*)bytes
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)length
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
2002-08-27 12:26:17 +00:00
|
|
|
|
d = [d initWithBytesNoCopy: bytes length: length freeWhenDone: YES];
|
|
|
|
|
return AUTORELEASE(d);
|
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an autoreleased data object encapsulating the data at bytes
|
|
|
|
|
* and with the specified length. Invokes
|
|
|
|
|
* -initWithBytesNoCopy:length:freeWhenDone:
|
|
|
|
|
*/
|
2002-10-05 17:47:54 +00:00
|
|
|
|
+ (id) dataWithBytesNoCopy: (void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)bufferSize
|
2002-08-27 12:26:17 +00:00
|
|
|
|
freeWhenDone: (BOOL)shouldFree
|
|
|
|
|
{
|
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
if (shouldFree == YES)
|
|
|
|
|
{
|
|
|
|
|
d = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
d = [dataStatic allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
}
|
2002-10-05 17:47:54 +00:00
|
|
|
|
d = [d initWithBytesNoCopy: aBuffer
|
|
|
|
|
length: bufferSize
|
|
|
|
|
freeWhenDone: shouldFree];
|
1999-07-03 19:59:44 +00:00
|
|
|
|
return AUTORELEASE(d);
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a data object encapsulating the contents of the specified file.
|
|
|
|
|
* Invokes -initWithContentsOfFile:
|
|
|
|
|
*/
|
1997-09-29 14:39:53 +00:00
|
|
|
|
+ (id) dataWithContentsOfFile: (NSString*)path
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithContentsOfFile: path];
|
|
|
|
|
return AUTORELEASE(d);
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a data object encapsulating the contents of the specified
|
|
|
|
|
* file mapped directly into memory.
|
|
|
|
|
* Invokes -initWithContentsOfMappedFile:
|
|
|
|
|
*/
|
1995-04-09 02:20:37 +00:00
|
|
|
|
+ (id) dataWithContentsOfMappedFile: (NSString*)path
|
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_MMAP
|
1999-07-03 19:59:44 +00:00
|
|
|
|
d = [NSDataMappedFile allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithContentsOfMappedFile: path];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#else
|
1999-07-03 19:59:44 +00:00
|
|
|
|
d = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithContentsOfMappedFile: path];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#endif
|
1999-07-03 19:59:44 +00:00
|
|
|
|
return AUTORELEASE(d);
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Retrieves the information at the specified url and returns an NSData
|
|
|
|
|
* instance encapsulating it.
|
|
|
|
|
*/
|
2000-09-22 13:45:58 +00:00
|
|
|
|
+ (id) dataWithContentsOfURL: (NSURL*)url
|
|
|
|
|
{
|
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [url resourceDataUsingCache: YES];
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an autoreleased instance initialised by copying the contents of data.
|
|
|
|
|
*/
|
1998-01-19 15:20:15 +00:00
|
|
|
|
+ (id) dataWithData: (NSData*)data
|
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytes: [data bytes] length: [data length]];
|
|
|
|
|
return AUTORELEASE(d);
|
1998-01-19 15:20:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a new empty data object.
|
|
|
|
|
*/
|
2000-07-03 11:47:17 +00:00
|
|
|
|
+ (id) new
|
|
|
|
|
{
|
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
2002-08-27 12:26:17 +00:00
|
|
|
|
d = [d initWithBytesNoCopy: 0 length: 0 freeWhenDone: YES];
|
2000-07-03 11:47:17 +00:00
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-15 05:03:16 +00:00
|
|
|
|
- (id) init
|
1995-08-02 14:51:26 +00:00
|
|
|
|
{
|
2002-08-27 12:26:17 +00:00
|
|
|
|
return [self initWithBytesNoCopy: 0 length: 0 freeWhenDone: YES];
|
1995-08-02 14:51:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Makes a copy of bufferSize bytes of data at aBuffer, and passes it to
|
|
|
|
|
* -initWithBytesNoCopy:length:freeWhenDone: with a YES argument in order
|
|
|
|
|
* to initialise the receiver. Returns the result.
|
|
|
|
|
*/
|
1998-10-15 05:03:16 +00:00
|
|
|
|
- (id) initWithBytes: (const void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)bufferSize
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
2000-10-09 04:41:18 +00:00
|
|
|
|
void *ptr = 0;
|
2000-09-27 15:26:16 +00:00
|
|
|
|
|
2000-10-09 04:41:18 +00:00
|
|
|
|
if (bufferSize > 0)
|
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (aBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"[%@-initWithBytes:length:] called with "
|
|
|
|
|
@"length but null bytes", NSStringFromClass([self class])];
|
|
|
|
|
}
|
2009-02-11 17:33:31 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
ptr = NSAllocateCollectable(bufferSize, 0);
|
|
|
|
|
#else
|
2000-10-09 04:41:18 +00:00
|
|
|
|
ptr = NSZoneMalloc(NSDefaultMallocZone(), bufferSize);
|
2009-02-11 17:33:31 +00:00
|
|
|
|
#endif
|
2002-10-07 13:46:22 +00:00
|
|
|
|
if (ptr == 0)
|
2009-08-12 07:49:42 +00:00
|
|
|
|
{
|
2002-10-07 13:46:22 +00:00
|
|
|
|
DESTROY(self);
|
|
|
|
|
return nil;
|
2009-08-12 07:49:42 +00:00
|
|
|
|
}
|
2000-10-09 04:41:18 +00:00
|
|
|
|
memcpy(ptr, aBuffer, bufferSize);
|
|
|
|
|
}
|
2002-08-27 12:26:17 +00:00
|
|
|
|
return [self initWithBytesNoCopy: ptr
|
|
|
|
|
length: bufferSize
|
|
|
|
|
freeWhenDone: YES];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Invokes -initWithBytesNoCopy:length:freeWhenDone: with the last argument
|
|
|
|
|
* set to YES. Returns the resulting initialised data object (which may not
|
|
|
|
|
* be the receiver).
|
|
|
|
|
*/
|
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)bufferSize
|
2002-08-27 12:26:17 +00:00
|
|
|
|
{
|
|
|
|
|
return [self initWithBytesNoCopy: aBuffer
|
|
|
|
|
length: bufferSize
|
|
|
|
|
freeWhenDone: YES];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
/** <init /><override-subclass />
|
2002-10-04 09:08:09 +00:00
|
|
|
|
* Initialises the receiver.<br />
|
|
|
|
|
* The value of aBuffer is a pointer to something to be stored.<br />
|
|
|
|
|
* The value of bufferSize is the number of bytes to use.<br />
|
2003-11-28 22:41:07 +00:00
|
|
|
|
* The value of shouldFree specifies whether the receiver should
|
2002-10-04 09:08:09 +00:00
|
|
|
|
* attempt to free the memory pointer to by aBuffer when the receiver
|
|
|
|
|
* is deallocated ... ie. it says whether the receiver <em>owns</em>
|
2002-10-05 17:47:54 +00:00
|
|
|
|
* the memory. Supplying the wrong value here will lead to memory
|
|
|
|
|
* leaks or crashes.
|
2002-08-27 12:26:17 +00:00
|
|
|
|
*/
|
1998-10-15 05:03:16 +00:00
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)bufferSize
|
2002-08-27 12:26:17 +00:00
|
|
|
|
freeWhenDone: (BOOL)shouldFree
|
1998-10-15 05:03:16 +00:00
|
|
|
|
{
|
2000-09-27 15:26:16 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return nil;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialises the receiver with the contents of the specified file.<br />
|
2002-10-04 09:08:09 +00:00
|
|
|
|
* Returns the resulting object.<br />
|
|
|
|
|
* Returns nil if the file does not exist or can not be read for some reason.
|
2002-08-27 12:26:17 +00:00
|
|
|
|
*/
|
|
|
|
|
- (id) initWithContentsOfFile: (NSString*)path
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
2000-09-27 15:26:16 +00:00
|
|
|
|
void *fileBytes;
|
|
|
|
|
unsigned fileLength;
|
|
|
|
|
|
|
|
|
|
#if GS_WITH_GC
|
2009-03-10 09:35:14 +00:00
|
|
|
|
if (readContentsOfFile(path, &fileBytes, &fileLength, 0) == NO)
|
2000-09-27 15:26:16 +00:00
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
return nil;
|
2000-09-27 15:26:16 +00:00
|
|
|
|
}
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#else
|
2010-03-05 09:30:18 +00:00
|
|
|
|
if (readContentsOfFile(path, &fileBytes, &fileLength, [self zone]) == NO)
|
2000-09-27 15:26:16 +00:00
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
DESTROY(self);
|
|
|
|
|
return nil;
|
2000-09-27 15:26:16 +00:00
|
|
|
|
}
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#endif
|
|
|
|
|
self = [self initWithBytesNoCopy: fileBytes
|
|
|
|
|
length: fileLength
|
|
|
|
|
freeWhenDone: YES];
|
2000-09-27 15:26:16 +00:00
|
|
|
|
return self;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialize with data pointing to contents of file at path. Bytes are
|
|
|
|
|
* only "swapped in" as needed. File should not be moved or deleted for
|
|
|
|
|
* the life of this object.
|
|
|
|
|
*/
|
2001-12-17 14:31:42 +00:00
|
|
|
|
- (id) initWithContentsOfMappedFile: (NSString *)path
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_MMAP
|
2010-03-05 09:30:18 +00:00
|
|
|
|
NSZone *z = [self zone];
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2003-03-23 07:06:27 +00:00
|
|
|
|
self = [NSDataMappedFile allocWithZone: z];
|
2000-09-27 15:26:16 +00:00
|
|
|
|
return [self initWithContentsOfMappedFile: path];
|
|
|
|
|
#else
|
|
|
|
|
return [self initWithContentsOfFile: path];
|
|
|
|
|
#endif
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialize with data pointing to contents of URL, which will be
|
|
|
|
|
* retrieved immediately in a blocking manner.
|
|
|
|
|
*/
|
2000-09-22 13:45:58 +00:00
|
|
|
|
- (id) initWithContentsOfURL: (NSURL*)url
|
|
|
|
|
{
|
|
|
|
|
NSData *data = [url resourceDataUsingCache: YES];
|
|
|
|
|
|
2000-09-27 15:26:16 +00:00
|
|
|
|
return [self initWithData: data];
|
2000-09-22 13:45:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initializes by copying data's bytes into a new buffer.
|
|
|
|
|
*/
|
1995-04-09 02:20:37 +00:00
|
|
|
|
- (id) initWithData: (NSData*)data
|
|
|
|
|
{
|
2000-09-27 15:26:16 +00:00
|
|
|
|
if (data == nil)
|
|
|
|
|
{
|
2002-08-27 12:26:17 +00:00
|
|
|
|
return [self initWithBytesNoCopy: 0 length: 0 freeWhenDone: YES];
|
2000-09-27 15:26:16 +00:00
|
|
|
|
}
|
|
|
|
|
if ([data isKindOfClass: [NSData class]] == NO)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"-initWithData: passed a non-data object");
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2000-09-27 15:26:16 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
2000-06-27 16:18:02 +00:00
|
|
|
|
return [self initWithBytes: [data bytes] length: [data length]];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
|
// Accessing Data
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/** <override-subclass>
|
|
|
|
|
* Returns a pointer to the data encapsulated by the receiver.
|
|
|
|
|
*/
|
1995-04-09 02:20:37 +00:00
|
|
|
|
- (const void*) bytes
|
|
|
|
|
{
|
1998-10-20 14:40:05 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
2005-06-04 07:22:51 +00:00
|
|
|
|
return 0;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a short description of this object.
|
|
|
|
|
*/
|
1995-04-09 02:20:37 +00:00
|
|
|
|
- (NSString*) description
|
|
|
|
|
{
|
2002-11-27 13:56:00 +00:00
|
|
|
|
extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*);
|
2002-11-10 09:29:45 +00:00
|
|
|
|
NSMutableString *result = nil;
|
|
|
|
|
|
2002-11-27 13:56:00 +00:00
|
|
|
|
GSPropertyListMake(self, nil, NO, YES, 0, &result);
|
2002-11-10 09:29:45 +00:00
|
|
|
|
return result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Copies the contents of the memory encapsulated by the receiver into
|
|
|
|
|
* the specified buffer. The buffer must be large enough to contain
|
|
|
|
|
* -length bytes of data ... if it isn't then a crash is likely to occur.<br />
|
|
|
|
|
* Invokes -getBytes:range: with the range set to the whole of the receiver.
|
|
|
|
|
*/
|
2000-06-27 16:18:02 +00:00
|
|
|
|
- (void) getBytes: (void*)buffer
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self getBytes: buffer range: NSMakeRange(0, [self length])];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Copies length bytes of data from the memory encapsulated by the receiver
|
|
|
|
|
* into the specified buffer. The buffer must be large enough to contain
|
|
|
|
|
* length bytes of data ... if it isn't then a crash is likely to occur.<br />
|
2008-11-20 00:05:41 +00:00
|
|
|
|
* If length is greater than the size of the receiver, only the available
|
|
|
|
|
* bytes are copied.
|
2002-10-04 09:08:09 +00:00
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) getBytes: (void*)buffer length: (NSUInteger)length
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
2008-11-20 00:05:41 +00:00
|
|
|
|
NSUInteger l = [self length];
|
|
|
|
|
|
|
|
|
|
[self getBytes: buffer range: NSMakeRange(0, l < length ? l : length)];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Copies data from the memory encapsulated by the receiver (in the range
|
|
|
|
|
* specified by aRange) into the specified buffer.<br />
|
|
|
|
|
* The buffer must be large enough to contain the data ... if it isn't then
|
|
|
|
|
* a crash is likely to occur.<br />
|
|
|
|
|
* If aRange specifies a range which does not entirely lie within the
|
|
|
|
|
* receiver, an exception is raised.
|
|
|
|
|
*/
|
2000-06-27 16:18:02 +00:00
|
|
|
|
- (void) getBytes: (void*)buffer range: (NSRange)aRange
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
|
unsigned size = [self length];
|
|
|
|
|
|
|
|
|
|
GS_RANGE_CHECK(aRange, size);
|
|
|
|
|
memcpy(buffer, [self bytes] + aRange.location, aRange.length);
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-10-28 14:37:53 +00:00
|
|
|
|
- (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder
|
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
return self;
|
1997-10-28 14:37:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
2005-11-06 13:53:40 +00:00
|
|
|
|
* Returns an NSData instance encapsulating the memory from the receiver
|
2002-10-04 09:08:09 +00:00
|
|
|
|
* specified by the range aRange.<br />
|
|
|
|
|
* If aRange specifies a range which does not entirely lie within the
|
|
|
|
|
* receiver, an exception is raised.
|
|
|
|
|
*/
|
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];
|
|
|
|
|
|
1999-06-21 08:30:26 +00:00
|
|
|
|
GS_RANGE_CHECK(aRange, l);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
1999-09-29 20:15:17 +00:00
|
|
|
|
#if GS_WITH_GC
|
2009-03-10 09:35:14 +00:00
|
|
|
|
buffer = NSAllocateCollectable(aRange.length, 0);
|
1999-09-29 20:15:17 +00:00
|
|
|
|
#else
|
2009-03-10 09:35:14 +00:00
|
|
|
|
buffer = NSZoneMalloc(NSDefaultMallocZone(), aRange.length);
|
1999-09-29 20:15:17 +00:00
|
|
|
|
#endif
|
1997-09-29 14:39:53 +00:00
|
|
|
|
if (buffer == 0)
|
2002-10-07 13:46:22 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
|
format: @"No memory for subdata of NSData object"];
|
|
|
|
|
}
|
1998-10-20 14:40:05 +00:00
|
|
|
|
[self getBytes: buffer range: aRange];
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
1998-10-20 14:40:05 +00:00
|
|
|
|
return [NSData dataWithBytesNoCopy: buffer length: aRange.length];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (NSUInteger) hash
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2000-03-16 12:41:01 +00:00
|
|
|
|
unsigned char buf[64];
|
|
|
|
|
unsigned l = [self length];
|
|
|
|
|
unsigned ret =0;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-03-16 12:41:01 +00:00
|
|
|
|
l = MIN(l,64);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* hash for empty data matches hash for empty string
|
|
|
|
|
*/
|
|
|
|
|
if (l == 0)
|
|
|
|
|
{
|
|
|
|
|
return 0xfffffffe;
|
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2000-03-16 12:41:01 +00:00
|
|
|
|
[self getBytes: &buf range: NSMakeRange(0, l)];
|
|
|
|
|
|
|
|
|
|
while (l-- > 0)
|
|
|
|
|
{
|
2005-02-22 11:22:44 +00:00
|
|
|
|
ret = (ret << 5) + ret + buf[l];
|
2000-03-16 12:41:01 +00:00
|
|
|
|
}
|
|
|
|
|
// Again, match NSString
|
|
|
|
|
if (ret == 0)
|
|
|
|
|
{
|
|
|
|
|
ret = 0xffffffff;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-04-13 15:03:10 +00:00
|
|
|
|
- (BOOL) isEqual: anObject
|
|
|
|
|
{
|
1998-10-20 14:40:05 +00:00
|
|
|
|
if ([anObject isKindOfClass: [NSData class]])
|
|
|
|
|
return [self isEqualToData: anObject];
|
1995-04-13 15:03:10 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a boolean value indicating if the receiver and other contain
|
|
|
|
|
* identical data (using a byte by byte comparison). Assumes that the
|
|
|
|
|
* other object is an NSData instance ... may raise an exception if it isn't.
|
|
|
|
|
*/
|
2001-12-17 14:31:42 +00:00
|
|
|
|
- (BOOL) isEqualToData: (NSData*)other
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
2009-02-23 20:42:32 +00:00
|
|
|
|
NSUInteger len;
|
2002-10-04 09:08:09 +00:00
|
|
|
|
if (other == self)
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
if ((len = [self length]) != [other length])
|
2002-10-04 09:08:09 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
return (memcmp([self bytes], [other bytes], len) ? NO : YES);
|
|
|
|
|
}
|
|
|
|
|
|
2002-10-04 09:08:09 +00:00
|
|
|
|
/** <override-subclass>
|
|
|
|
|
* Returns the number of bytes of data encapsulated by the receiver.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (NSUInteger) length
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1995-04-20 16:02:26 +00:00
|
|
|
|
/* This is left to concrete subclasses to implement. */
|
1998-10-20 14:40:05 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-27 16:18:02 +00:00
|
|
|
|
- (BOOL) writeToFile: (NSString*)path atomically: (BOOL)useAuxiliaryFile
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-02-01 14:00:17 +00:00
|
|
|
|
if (useAuxiliaryFile)
|
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
return [self writeToFile: path options: NSAtomicWrite error: 0];
|
1999-02-01 14:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
return [self writeToFile: path options: 0 error: 0];
|
1999-02-01 14:00:17 +00:00
|
|
|
|
}
|
2009-04-27 08:16:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) writeToURL: (NSURL*)anURL atomically: (BOOL)flag
|
|
|
|
|
{
|
|
|
|
|
if (flag)
|
1995-04-20 16:02:26 +00:00
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
return [self writeToURL: anURL options: NSAtomicWrite error: 0];
|
1995-04-20 16:02:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
return [self writeToURL: anURL options: 0 error: 0];
|
1995-04-20 16:02:26 +00:00
|
|
|
|
}
|
2009-04-27 08:16:06 +00:00
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
2009-04-27 08:16:06 +00:00
|
|
|
|
|
|
|
|
|
// Deserializing Data
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
2009-04-27 08:16:06 +00:00
|
|
|
|
/**
|
|
|
|
|
* Copies data from buffer starting from cursor. <strong>Deprecated</strong>.
|
|
|
|
|
* Use [-getBytes:] and related methods instead.
|
|
|
|
|
*/
|
|
|
|
|
- (unsigned int) deserializeAlignedBytesLengthAtCursor: (unsigned int*)cursor
|
|
|
|
|
{
|
|
|
|
|
return (unsigned)[self deserializeIntAtCursor: cursor];
|
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
2009-04-27 08:16:06 +00:00
|
|
|
|
/**
|
|
|
|
|
* Copies data from buffer starting from cursor. <strong>Deprecated</strong>.
|
|
|
|
|
* Use [-getBytes:] and related methods instead.
|
|
|
|
|
*/
|
|
|
|
|
- (void) deserializeBytes: (void*)buffer
|
|
|
|
|
length: (unsigned int)bytes
|
|
|
|
|
atCursor: (unsigned int*)cursor
|
|
|
|
|
{
|
|
|
|
|
NSRange range = { *cursor, bytes };
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
2009-04-27 08:16:06 +00:00
|
|
|
|
[self getBytes: buffer range: range];
|
|
|
|
|
*cursor += bytes;
|
|
|
|
|
}
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
2009-04-27 08:16:06 +00:00
|
|
|
|
- (void) deserializeDataAt: (void*)data
|
|
|
|
|
ofObjCType: (const char*)type
|
|
|
|
|
atCursor: (unsigned int*)cursor
|
|
|
|
|
context: (id <NSObjCTypeSerializationCallBack>)callback
|
|
|
|
|
{
|
|
|
|
|
if (!type || !data)
|
|
|
|
|
return;
|
1995-04-20 16:02:26 +00:00
|
|
|
|
|
2009-04-27 08:16:06 +00:00
|
|
|
|
switch (*type)
|
1995-04-20 16:02:26 +00:00
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
case _C_ID:
|
2002-09-16 14:04:24 +00:00
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
[callback deserializeObjectAt: data
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
fromData: self
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
return;
|
2002-09-16 14:25:06 +00:00
|
|
|
|
}
|
2009-04-27 08:16:06 +00:00
|
|
|
|
case _C_CHARPTR:
|
2005-07-30 15:44:45 +00:00
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
int32_t length;
|
2005-07-30 15:44:45 +00:00
|
|
|
|
|
2009-04-27 08:16:06 +00:00
|
|
|
|
[self deserializeBytes: &length
|
|
|
|
|
length: sizeof(length)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
length = GSSwapBigI32ToHost(length);
|
|
|
|
|
if (length == -1)
|
2005-07-30 15:44:45 +00:00
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
*(const char**)data = 0;
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
unsigned len = (length+1)*sizeof(char);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
*(char**)data = (char*)NSAllocateCollectable(len, 0);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
#else
|
2009-03-10 09:35:14 +00:00
|
|
|
|
*(char**)data = (char*)NSZoneMalloc(NSDefaultMallocZone(), len);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
#endif
|
2002-10-07 13:46:22 +00:00
|
|
|
|
if (*(char**)data == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
|
format: @"out of memory to deserialize bytes"];
|
|
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: *(char**)data
|
|
|
|
|
length: length
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
(*(char**)data)[length] = '\0';
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_ARY_B:
|
|
|
|
|
{
|
|
|
|
|
unsigned offset = 0;
|
|
|
|
|
unsigned size;
|
|
|
|
|
unsigned count = atoi(++type);
|
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
while (isdigit(*type))
|
|
|
|
|
{
|
|
|
|
|
type++;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
size = objc_sizeof_type(type);
|
1998-10-20 14:40:05 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
[self deserializeDataAt: (char*)data + offset
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: callback];
|
|
|
|
|
offset += size;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_STRUCT_B:
|
|
|
|
|
{
|
2003-04-10 16:26:09 +00:00
|
|
|
|
struct objc_struct_layout layout;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
|
2003-04-10 16:26:09 +00:00
|
|
|
|
objc_layout_structure (type, &layout);
|
|
|
|
|
while (objc_layout_structure_next_member (&layout))
|
1999-01-27 12:49:49 +00:00
|
|
|
|
{
|
2005-07-08 11:48:37 +00:00
|
|
|
|
unsigned offset;
|
|
|
|
|
unsigned align;
|
2003-04-10 16:26:09 +00:00
|
|
|
|
const char *ftype;
|
|
|
|
|
|
|
|
|
|
objc_layout_structure_get_info (&layout, &offset, &align, &ftype);
|
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeDataAt: ((char*)data) + offset
|
2003-04-10 16:26:09 +00:00
|
|
|
|
ofObjCType: ftype
|
1999-01-27 12:49:49 +00:00
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: callback];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_PTR:
|
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
unsigned len = objc_sizeof_type(++type);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
*(char**)data = (char*)NSAllocateCollectable(len, 0);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
#else
|
2009-03-10 09:35:14 +00:00
|
|
|
|
*(char**)data = (char*)NSZoneMalloc(NSDefaultMallocZone(), len);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
#endif
|
2002-10-07 13:46:22 +00:00
|
|
|
|
if (*(char**)data == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
|
format: @"out of memory to deserialize bytes"];
|
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeDataAt: *(char**)data
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: callback];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_CHR:
|
|
|
|
|
case _C_UCHR:
|
|
|
|
|
{
|
|
|
|
|
[self deserializeBytes: data
|
|
|
|
|
length: sizeof(unsigned char)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_SHT:
|
|
|
|
|
case _C_USHT:
|
|
|
|
|
{
|
|
|
|
|
unsigned short ns;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &ns
|
|
|
|
|
length: sizeof(unsigned short)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
*(unsigned short*)data = NSSwapBigShortToHost(ns);
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_INT:
|
|
|
|
|
case _C_UINT:
|
|
|
|
|
{
|
|
|
|
|
unsigned ni;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &ni
|
|
|
|
|
length: sizeof(unsigned)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
*(unsigned*)data = NSSwapBigIntToHost(ni);
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_LNG:
|
|
|
|
|
case _C_ULNG:
|
|
|
|
|
{
|
|
|
|
|
unsigned long nl;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &nl
|
|
|
|
|
length: sizeof(unsigned long)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
*(unsigned long*)data = NSSwapBigLongToHost(nl);
|
|
|
|
|
return;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_LNG_LNG:
|
|
|
|
|
case _C_ULNG_LNG:
|
|
|
|
|
{
|
|
|
|
|
unsigned long long nl;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &nl
|
|
|
|
|
length: sizeof(unsigned long long)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
*(unsigned long long*)data = NSSwapBigLongLongToHost(nl);
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_FLT:
|
|
|
|
|
{
|
|
|
|
|
NSSwappedFloat nf;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &nf
|
|
|
|
|
length: sizeof(NSSwappedFloat)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
*(float*)data = NSSwapBigFloatToHost(nf);
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_DBL:
|
|
|
|
|
{
|
|
|
|
|
NSSwappedDouble nd;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &nd
|
|
|
|
|
length: sizeof(NSSwappedDouble)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
*(double*)data = NSSwapBigDoubleToHost(nd);
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_CLASS:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t ni;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
[self deserializeBytes: &ni
|
1999-02-01 12:05:15 +00:00
|
|
|
|
length: sizeof(ni)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
atCursor: cursor];
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapBigI16ToHost(ni);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (ni == 0)
|
|
|
|
|
{
|
|
|
|
|
*(Class*)data = 0;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char name[ni+1];
|
|
|
|
|
Class c;
|
|
|
|
|
|
|
|
|
|
[self deserializeBytes: name
|
|
|
|
|
length: ni
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
name[ni] = '\0';
|
2010-02-22 10:13:20 +00:00
|
|
|
|
c = objc_lookUpClass(name);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (c == 0)
|
|
|
|
|
{
|
2002-02-21 13:31:13 +00:00
|
|
|
|
NSLog(@"[%s %s] can't find class - %s",
|
2010-02-22 10:13:20 +00:00
|
|
|
|
class_getName([self class]),
|
|
|
|
|
sel_getName(_cmd), name);
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
*(Class*)data = c;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
case _C_SEL:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t ln;
|
|
|
|
|
uint16_t lt;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
[self deserializeBytes: &ln
|
1999-02-01 12:05:15 +00:00
|
|
|
|
length: sizeof(ln)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
atCursor: cursor];
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ln = GSSwapBigI16ToHost(ln);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: <
|
1999-02-01 12:05:15 +00:00
|
|
|
|
length: sizeof(lt)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
atCursor: cursor];
|
1999-02-08 10:46:32 +00:00
|
|
|
|
lt = GSSwapBigI16ToHost(lt);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (ln == 0)
|
|
|
|
|
{
|
|
|
|
|
*(SEL*)data = 0;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char name[ln+1];
|
|
|
|
|
char types[lt+1];
|
|
|
|
|
SEL sel;
|
|
|
|
|
|
|
|
|
|
[self deserializeBytes: name
|
|
|
|
|
length: ln
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
name[ln] = '\0';
|
|
|
|
|
[self deserializeBytes: types
|
|
|
|
|
length: lt
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
types[lt] = '\0';
|
|
|
|
|
|
|
|
|
|
if (lt)
|
|
|
|
|
{
|
2011-02-20 07:58:11 +00:00
|
|
|
|
sel = GSSelectorFromNameAndTypes(name, types);
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2010-12-23 02:23:05 +00:00
|
|
|
|
sel = sel_registerName(name);
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (sel == 0)
|
|
|
|
|
{
|
2000-10-26 14:12:44 +00:00
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"can't make sel with name '%s' "
|
|
|
|
|
@"and types '%s'", name, types];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
*(SEL*)data = sel;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
default:
|
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"Unknown type to deserialize - '%s'", type];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Retrieve an int from this data, which is assumed to be in network
|
|
|
|
|
* (big-endian) byte order. Cursor refers to byte position.
|
|
|
|
|
*/
|
2001-12-17 14:31:42 +00:00
|
|
|
|
- (int) deserializeIntAtCursor: (unsigned int*)cursor
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
unsigned ni, result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &ni length: sizeof(unsigned) atCursor: cursor];
|
|
|
|
|
result = NSSwapBigIntToHost(ni);
|
|
|
|
|
return result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Retrieve an int from this data, which is assumed to be in network
|
|
|
|
|
* (big-endian) byte order. Index refers to byte position.
|
|
|
|
|
*/
|
2001-12-17 14:31:42 +00:00
|
|
|
|
- (int) deserializeIntAtIndex: (unsigned int)index
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
unsigned ni, result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &ni length: sizeof(unsigned) atCursor: &index];
|
|
|
|
|
result = NSSwapBigIntToHost(ni);
|
|
|
|
|
return result;
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Retrieve ints from intBuffer, which is assumed to be in network (big-endian)
|
|
|
|
|
* byte order. Count refers to number of ints, but index refers to byte
|
|
|
|
|
* position.
|
|
|
|
|
*/
|
1999-01-27 12:49:49 +00:00
|
|
|
|
- (void) deserializeInts: (int*)intBuffer
|
2001-12-17 14:31:42 +00:00
|
|
|
|
count: (unsigned int)numInts
|
|
|
|
|
atCursor: (unsigned int*)cursor
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
unsigned i;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &intBuffer
|
|
|
|
|
length: numInts * sizeof(unsigned)
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
for (i = 0; i < numInts; i++)
|
|
|
|
|
intBuffer[i] = NSSwapBigIntToHost(intBuffer[i]);
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Retrieve ints from intBuffer, which is assumed to be in network (big-endian)
|
|
|
|
|
* byte order. Count refers to number of ints, but index refers to byte
|
|
|
|
|
* position.
|
|
|
|
|
*/
|
1999-01-27 12:49:49 +00:00
|
|
|
|
- (void) deserializeInts: (int*)intBuffer
|
2001-12-17 14:31:42 +00:00
|
|
|
|
count: (unsigned int)numInts
|
|
|
|
|
atIndex: (unsigned int)index
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
unsigned i;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeBytes: &intBuffer
|
|
|
|
|
length: numInts * sizeof(int)
|
|
|
|
|
atCursor: &index];
|
|
|
|
|
for (i = 0; i < numInts; i++)
|
|
|
|
|
{
|
|
|
|
|
intBuffer[i] = NSSwapBigIntToHost(intBuffer[i]);
|
1998-10-20 14:40:05 +00:00
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-11-12 10:58:17 +00:00
|
|
|
|
- (id) copyWithZone: (NSZone*)z
|
1995-04-09 02:20:37 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (NSShouldRetainWithZone(self, z) &&
|
1998-03-12 14:21:20 +00:00
|
|
|
|
[self isKindOfClass: [NSMutableData class]] == NO)
|
1999-07-03 19:59:44 +00:00
|
|
|
|
return RETAIN(self);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
else
|
|
|
|
|
return [[dataMalloc allocWithZone: z]
|
|
|
|
|
initWithBytes: [self bytes] length: [self length]];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) mutableCopyWithZone: (NSZone*)zone
|
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
return [[mutableDataMalloc allocWithZone: zone]
|
1998-03-12 14:21:20 +00:00
|
|
|
|
initWithBytes: [self bytes] length: [self length]];
|
1995-04-09 02:20:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-20 14:40:05 +00:00
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)coder
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2007-10-03 05:36:07 +00:00
|
|
|
|
if ([coder allowsKeyedCoding])
|
2006-08-07 04:14:58 +00:00
|
|
|
|
{
|
|
|
|
|
[coder encodeObject: self];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[coder encodeDataObject: self];
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-20 14:40:05 +00:00
|
|
|
|
- (id) initWithCoder: (NSCoder*)coder
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2006-08-07 04:14:58 +00:00
|
|
|
|
id obj = nil;
|
|
|
|
|
|
2007-10-03 05:36:07 +00:00
|
|
|
|
if ([coder allowsKeyedCoding])
|
2006-08-07 04:14:58 +00:00
|
|
|
|
{
|
2007-12-03 18:08:58 +00:00
|
|
|
|
// FIXME
|
2006-08-07 04:14:58 +00:00
|
|
|
|
obj = [coder decodeObject];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
obj = [coder decodeDataObject];
|
|
|
|
|
}
|
2000-06-27 16:18:02 +00:00
|
|
|
|
|
|
|
|
|
if (obj != self)
|
|
|
|
|
{
|
|
|
|
|
ASSIGN(self, obj);
|
|
|
|
|
}
|
|
|
|
|
return self;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-06-06 13:57:06 +00:00
|
|
|
|
- (BOOL) writeToFile: (NSString *)path
|
|
|
|
|
options: (NSUInteger)writeOptionsMask
|
|
|
|
|
error: (NSError **)errorPtr
|
|
|
|
|
{
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
NSUInteger length = [path length];
|
|
|
|
|
unichar wthePath[length + 100];
|
|
|
|
|
unichar wtheRealPath[length + 100];
|
|
|
|
|
#else
|
|
|
|
|
char thePath[BUFSIZ*2+8];
|
|
|
|
|
char theRealPath[BUFSIZ*2];
|
|
|
|
|
#endif
|
|
|
|
|
int c;
|
|
|
|
|
FILE *theFile;
|
|
|
|
|
BOOL useAuxiliaryFile = NO;
|
|
|
|
|
BOOL error_BadPath = YES;
|
|
|
|
|
|
|
|
|
|
if (writeOptionsMask & NSAtomicWrite)
|
|
|
|
|
{
|
|
|
|
|
useAuxiliaryFile = YES;
|
|
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
[path getCharacters: wtheRealPath];
|
|
|
|
|
wtheRealPath[length] = L'\0';
|
|
|
|
|
error_BadPath = (length <= 0);
|
|
|
|
|
#else
|
|
|
|
|
if ([path canBeConvertedToEncoding: [NSString defaultCStringEncoding]])
|
|
|
|
|
{
|
|
|
|
|
const char *local_c_path = [path cString];
|
|
|
|
|
|
|
|
|
|
if (local_c_path != 0 && strlen(local_c_path) < (BUFSIZ*2))
|
|
|
|
|
{
|
|
|
|
|
strcpy(theRealPath,local_c_path);
|
|
|
|
|
error_BadPath = NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (error_BadPath)
|
|
|
|
|
{
|
|
|
|
|
NSWarnMLog(@"Open (%@) attempt failed - bad path",path);
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_MKSTEMP
|
|
|
|
|
if (useAuxiliaryFile)
|
|
|
|
|
{
|
|
|
|
|
int desc;
|
|
|
|
|
int mask;
|
|
|
|
|
|
|
|
|
|
strcpy(thePath, theRealPath);
|
|
|
|
|
strcat(thePath, "XXXXXX");
|
|
|
|
|
if ((desc = mkstemp(thePath)) < 0)
|
|
|
|
|
{
|
|
|
|
|
NSWarnMLog(@"mkstemp (%s) failed - %@", thePath, [NSError _last]);
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
mask = umask(0);
|
|
|
|
|
umask(mask);
|
|
|
|
|
fchmod(desc, 0644 & ~mask);
|
|
|
|
|
if ((theFile = fdopen(desc, "w")) == 0)
|
|
|
|
|
{
|
|
|
|
|
close(desc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy(thePath, theRealPath);
|
|
|
|
|
theFile = fopen(thePath, "wb");
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (useAuxiliaryFile)
|
|
|
|
|
{
|
|
|
|
|
/* 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. */
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
wcscpy(wthePath, wtheRealPath);
|
|
|
|
|
wcscat(wthePath, L"XXXXXX");
|
|
|
|
|
if (_wmktemp(wthePath) == 0)
|
|
|
|
|
{
|
|
|
|
|
NSWarnMLog(@"mktemp (%@) failed - %@",
|
|
|
|
|
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
|
|
|
|
[NSError _last]);
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
strcpy(thePath, theRealPath);
|
|
|
|
|
strcat(thePath, "XXXXXX");
|
|
|
|
|
if (mktemp(thePath) == 0)
|
|
|
|
|
{
|
|
|
|
|
NSWarnMLog(@"mktemp (%s) failed - %@", thePath, [NSError _last]);
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
wcscpy(wthePath,wtheRealPath);
|
|
|
|
|
#else
|
|
|
|
|
strcpy(thePath, theRealPath);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open the file (whether temp or real) for writing. */
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
theFile = _wfopen(wthePath, L"wb");
|
|
|
|
|
#else
|
|
|
|
|
theFile = fopen(thePath, "wb");
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (theFile == 0)
|
|
|
|
|
{
|
|
|
|
|
/* Something went wrong; we weren't
|
|
|
|
|
* even able to open the file. */
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
NSWarnMLog(@"Open (%@) failed - %@",
|
|
|
|
|
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
|
|
|
|
[NSError _last]);
|
|
|
|
|
#else
|
|
|
|
|
NSWarnMLog(@"Open (%s) failed - %@", thePath, [NSError _last]);
|
|
|
|
|
#endif
|
|
|
|
|
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. */
|
|
|
|
|
c = fwrite([self bytes], sizeof(char), [self length], theFile);
|
|
|
|
|
|
|
|
|
|
if (c < (int)[self length]) /* We failed to write everything for
|
|
|
|
|
* some reason. */
|
|
|
|
|
{
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
NSWarnMLog(@"Fwrite (%@) failed - %@",
|
|
|
|
|
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
|
|
|
|
[NSError _last]);
|
|
|
|
|
#else
|
|
|
|
|
NSWarnMLog(@"Fwrite (%s) failed - %@", thePath, [NSError _last]);
|
|
|
|
|
#endif
|
|
|
|
|
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. */
|
|
|
|
|
{
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
NSWarnMLog(@"Fclose (%@) failed - %@",
|
|
|
|
|
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
|
|
|
|
[NSError _last]);
|
|
|
|
|
#else
|
|
|
|
|
NSWarnMLog(@"Fclose (%s) failed - %@", thePath, [NSError _last]);
|
|
|
|
|
#endif
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we used a temporary file, we still need to rename() it be the
|
|
|
|
|
* real file. Also, we need to try to retain the file attributes of
|
|
|
|
|
* the original file we are overwriting (if we are) */
|
|
|
|
|
if (useAuxiliaryFile)
|
|
|
|
|
{
|
|
|
|
|
NSFileManager *mgr = [NSFileManager defaultManager];
|
|
|
|
|
NSMutableDictionary *att = nil;
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
NSUInteger perm;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ([mgr fileExistsAtPath: path])
|
|
|
|
|
{
|
|
|
|
|
att = [[mgr fileAttributesAtPath: path
|
|
|
|
|
traverseLink: YES] mutableCopy];
|
2010-01-10 14:38:16 +00:00
|
|
|
|
IF_NO_GC(AUTORELEASE(att));
|
2009-04-27 08:16:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
/* To replace the existing file on windows, it must be writable.
|
|
|
|
|
*/
|
|
|
|
|
perm = [att filePosixPermissions];
|
|
|
|
|
if (perm != NSNotFound && (perm & 0200) == 0)
|
|
|
|
|
{
|
|
|
|
|
[mgr changeFileAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
[NSNumber numberWithUnsignedInt: 0777], NSFilePosixPermissions,
|
|
|
|
|
nil] atPath: path];
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* The windoze implementation of the POSIX rename() function is buggy
|
|
|
|
|
* and doesn't work if the destination file already exists ... so we
|
|
|
|
|
* try to use a windoze specific function instead.
|
|
|
|
|
*/
|
|
|
|
|
#if 0
|
|
|
|
|
if (ReplaceFile(theRealPath, thePath, 0,
|
|
|
|
|
REPLACEFILE_IGNORE_MERGE_ERRORS, 0, 0) != 0)
|
|
|
|
|
{
|
|
|
|
|
c = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
c = -1;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (MoveFileExW(wthePath, wtheRealPath, MOVEFILE_REPLACE_EXISTING) != 0)
|
|
|
|
|
{
|
|
|
|
|
c = 0;
|
|
|
|
|
}
|
|
|
|
|
/* Windows 9x does not support MoveFileEx */
|
|
|
|
|
else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
|
|
|
|
{
|
|
|
|
|
unichar secondaryFile[length + 100];
|
|
|
|
|
|
|
|
|
|
wcscpy(secondaryFile, wthePath);
|
|
|
|
|
wcscat(secondaryFile, L"-delete");
|
|
|
|
|
// Delete the intermediate name just in case
|
|
|
|
|
DeleteFileW(secondaryFile);
|
|
|
|
|
// Move the existing file to the temp name
|
|
|
|
|
if (MoveFileW(wtheRealPath, secondaryFile) != 0)
|
|
|
|
|
{
|
|
|
|
|
if (MoveFileW(wthePath, wtheRealPath) != 0)
|
|
|
|
|
{
|
|
|
|
|
c = 0;
|
|
|
|
|
// Delete the old file if possible
|
|
|
|
|
DeleteFileW(secondaryFile);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
c = -1; // failure, restore the old file if possible
|
|
|
|
|
MoveFileW(secondaryFile, wtheRealPath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
c = -1; // failure
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
c = -1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#else
|
|
|
|
|
c = rename(thePath, theRealPath);
|
|
|
|
|
#endif
|
|
|
|
|
if (c != 0) /* Many things could go wrong, I guess. */
|
|
|
|
|
{
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
NSWarnMLog(@"Rename ('%@' to '%@') failed - %@",
|
|
|
|
|
[NSString stringWithCharacters: wthePath
|
|
|
|
|
length: wcslen(wthePath)],
|
|
|
|
|
[NSString stringWithCharacters: wtheRealPath
|
|
|
|
|
length: wcslen(wtheRealPath)],
|
|
|
|
|
[NSError _last]);
|
|
|
|
|
#else
|
|
|
|
|
NSWarnMLog(@"Rename ('%s' to '%s') failed - %@",
|
|
|
|
|
thePath, theRealPath, [NSError _last]);
|
|
|
|
|
#endif
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (att != nil)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* We have created a new file - so we attempt to make it's
|
|
|
|
|
* attributes match that of the original.
|
|
|
|
|
*/
|
|
|
|
|
[att removeObjectForKey: NSFileSize];
|
|
|
|
|
[att removeObjectForKey: NSFileModificationDate];
|
|
|
|
|
[att removeObjectForKey: NSFileReferenceCount];
|
|
|
|
|
[att removeObjectForKey: NSFileSystemNumber];
|
|
|
|
|
[att removeObjectForKey: NSFileSystemFileNumber];
|
|
|
|
|
[att removeObjectForKey: NSFileDeviceIdentifier];
|
|
|
|
|
[att removeObjectForKey: NSFileType];
|
|
|
|
|
if ([mgr changeFileAttributes: att atPath: path] == NO)
|
|
|
|
|
{
|
|
|
|
|
NSWarnMLog(@"Unable to correctly set all attributes for '%@'",
|
|
|
|
|
path);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#ifndef __MINGW__
|
2009-04-27 08:16:06 +00:00
|
|
|
|
else if (geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
|
|
|
|
|
{
|
|
|
|
|
att = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
NSFileOwnerAccountName, NSUserName(), nil];
|
|
|
|
|
if ([mgr changeFileAttributes: att atPath: path] == NO)
|
|
|
|
|
{
|
|
|
|
|
NSWarnMLog(@"Unable to correctly set ownership for '%@'", path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* success: */
|
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
|
|
/* Just in case the failure action needs to be changed. */
|
|
|
|
|
failure:
|
|
|
|
|
/*
|
|
|
|
|
* Attempt to tidy up by removing temporary file on failure.
|
|
|
|
|
*/
|
|
|
|
|
if (useAuxiliaryFile)
|
|
|
|
|
{
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2009-04-27 08:16:06 +00:00
|
|
|
|
_wunlink(wthePath);
|
|
|
|
|
#else
|
|
|
|
|
unlink(thePath);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2008-06-06 13:57:06 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) writeToURL: (NSURL *)url
|
|
|
|
|
options: (NSUInteger)writeOptionsMask
|
|
|
|
|
error: (NSError **)errorPtr
|
|
|
|
|
{
|
2009-04-27 08:16:06 +00:00
|
|
|
|
if ([url isFileURL] == YES)
|
|
|
|
|
{
|
|
|
|
|
return [self writeToFile: [url path]
|
|
|
|
|
options: writeOptionsMask
|
|
|
|
|
error: errorPtr];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return [url setResourceData: self];
|
|
|
|
|
}
|
2008-06-06 13:57:06 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
1995-04-09 02:20:37 +00:00
|
|
|
|
@end
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Provides some shared-memory extensions to [NSData].
|
|
|
|
|
*/
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@implementation NSData (GNUstepExtensions)
|
2004-06-22 22:40:40 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* New instance with given shared memory ID.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
+ (id) dataWithShmID: (int)anID length: (NSUInteger)length
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SHMCTL
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSDataShared *d;
|
|
|
|
|
|
|
|
|
|
d = [NSDataShared allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithShmID: anID length: length];
|
|
|
|
|
return AUTORELEASE(d);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#else
|
|
|
|
|
NSLog(@"[NSData -dataWithSmdID:length:] no shared memory support");
|
|
|
|
|
return nil;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* New instance with given bytes in shared memory.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
+ (id) dataWithSharedBytes: (const void*)bytes length: (NSUInteger)length
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SHMCTL
|
1999-07-03 19:59:44 +00:00
|
|
|
|
d = [NSDataShared allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytes: bytes length: length];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#else
|
1999-07-03 19:59:44 +00:00
|
|
|
|
d = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytes: bytes length: length];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#endif
|
1999-07-03 19:59:44 +00:00
|
|
|
|
return AUTORELEASE(d);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
+ (id) dataWithStaticBytes: (const void*)bytes length: (NSUInteger)length
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSDataStatic *d;
|
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
d = [dataStatic allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytesNoCopy: (void*)bytes length: length freeWhenDone: NO];
|
1999-07-03 19:59:44 +00:00
|
|
|
|
return AUTORELEASE(d);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
- (void) deserializeTypeTag: (unsigned char*)tag
|
|
|
|
|
andCrossRef: (unsigned int*)ref
|
2001-12-17 14:31:42 +00:00
|
|
|
|
atCursor: (unsigned int*)cursor
|
1998-10-23 15:48:21 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self deserializeDataAt: (void*)tag
|
2006-01-11 08:37:16 +00:00
|
|
|
|
ofObjCType: @encode(uint8_t)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: nil];
|
|
|
|
|
if (*tag & _GSC_MAYX)
|
|
|
|
|
{
|
|
|
|
|
switch (*tag & _GSC_SIZE)
|
|
|
|
|
{
|
|
|
|
|
case _GSC_X_0:
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case _GSC_X_1:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint8_t x;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
[self deserializeDataAt: (void*)&x
|
2006-01-11 08:37:16 +00:00
|
|
|
|
ofObjCType: @encode(uint8_t)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: nil];
|
|
|
|
|
*ref = (unsigned int)x;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case _GSC_X_2:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t x;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
[self deserializeDataAt: (void*)&x
|
2006-01-11 08:37:16 +00:00
|
|
|
|
ofObjCType: @encode(uint16_t)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: nil];
|
|
|
|
|
*ref = (unsigned int)x;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint32_t x;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
[self deserializeDataAt: (void*)&x
|
2006-01-11 08:37:16 +00:00
|
|
|
|
ofObjCType: @encode(uint32_t)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: nil];
|
|
|
|
|
*ref = (unsigned int)x;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-23 15:48:21 +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
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Mutable version of [NSData]. Methods are provided for appending and
|
|
|
|
|
* replacing bytes in the buffer, which will be grown as needed.
|
|
|
|
|
*/
|
1995-04-17 20:40:59 +00:00
|
|
|
|
@implementation NSMutableData
|
2000-04-14 10:38:22 +00:00
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2000-08-07 22:00:31 +00:00
|
|
|
|
if (self == NSMutableDataAbstract)
|
|
|
|
|
{
|
|
|
|
|
return NSAllocateObject(mutableDataMalloc, 0, z);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return NSAllocateObject(self, 0, z);
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-06-24 21:53:49 +00:00
|
|
|
|
+ (id) data
|
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSMutableData *d;
|
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithCapacity: 0];
|
|
|
|
|
return AUTORELEASE(d);
|
1998-06-24 21:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
+ (id) dataWithBytes: (const void*)bytes
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)length
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytes: bytes length: length];
|
|
|
|
|
return AUTORELEASE(d);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
+ (id) dataWithBytesNoCopy: (void*)bytes
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)length
|
1995-08-23 15:36:59 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytesNoCopy: bytes length: length];
|
|
|
|
|
return AUTORELEASE(d);
|
1995-08-23 15:36:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* New instance with buffer of given numBytes with length of valid data set
|
|
|
|
|
* to zero. Note that capacity will be automatically increased as necessary.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
+ (id) dataWithCapacity: (NSUInteger)numBytes
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSMutableData *d;
|
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithCapacity: numBytes];
|
|
|
|
|
return AUTORELEASE(d);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (id) dataWithContentsOfFile: (NSString*)path
|
|
|
|
|
{
|
2000-09-22 13:45:58 +00:00
|
|
|
|
NSMutableData *d;
|
1999-07-03 19:59:44 +00:00
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithContentsOfFile: path];
|
|
|
|
|
return AUTORELEASE(d);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (id) dataWithContentsOfMappedFile: (NSString*)path
|
|
|
|
|
{
|
2000-09-22 13:45:58 +00:00
|
|
|
|
NSMutableData *d;
|
1999-07-03 19:59:44 +00:00
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithContentsOfMappedFile: path];
|
|
|
|
|
return AUTORELEASE(d);
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-09-22 13:45:58 +00:00
|
|
|
|
+ (id) dataWithContentsOfURL: (NSURL*)url
|
|
|
|
|
{
|
|
|
|
|
NSMutableData *d;
|
|
|
|
|
NSData *data;
|
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
data = [url resourceDataUsingCache: YES];
|
|
|
|
|
d = [d initWithBytes: [data bytes] length: [data length]];
|
|
|
|
|
return AUTORELEASE(d);
|
|
|
|
|
}
|
|
|
|
|
|
1998-01-19 15:20:15 +00:00
|
|
|
|
+ (id) dataWithData: (NSData*)data
|
|
|
|
|
{
|
2000-09-22 13:45:58 +00:00
|
|
|
|
NSMutableData *d;
|
1999-07-03 19:59:44 +00:00
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytes: [data bytes] length: [data length]];
|
|
|
|
|
return AUTORELEASE(d);
|
1998-01-19 15:20:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* New instance with buffer of capacity and valid data size equal to given
|
|
|
|
|
* length in bytes. The buffer contents are set to zero. The length of
|
|
|
|
|
* valid data is set to zero. Note that buffer will be automatically
|
|
|
|
|
* increased as necessary.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
+ (id) dataWithLength: (NSUInteger)length
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSMutableData *d;
|
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithLength: length];
|
|
|
|
|
return AUTORELEASE(d);
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-07-03 11:47:17 +00:00
|
|
|
|
+ (id) new
|
|
|
|
|
{
|
|
|
|
|
NSMutableData *d;
|
|
|
|
|
|
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithCapacity: 0];
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2000-06-27 16:18:02 +00:00
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
|
|
|
|
unsigned length = [self length];
|
|
|
|
|
void *bytes = [self mutableBytes];
|
|
|
|
|
|
2007-12-03 18:08:58 +00:00
|
|
|
|
if ([aCoder allowsKeyedCoding])
|
2000-06-27 16:18:02 +00:00
|
|
|
|
{
|
2007-12-03 18:08:58 +00:00
|
|
|
|
[aCoder encodeBytes: bytes
|
|
|
|
|
length: length
|
|
|
|
|
forKey:@"NS.data"];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[aCoder encodeValueOfObjCType: @encode(unsigned int)
|
|
|
|
|
at: &length];
|
|
|
|
|
if (length)
|
|
|
|
|
{
|
|
|
|
|
[aCoder encodeArrayOfObjCType: @encode(unsigned char)
|
|
|
|
|
count: length
|
|
|
|
|
at: bytes];
|
|
|
|
|
}
|
2000-06-27 16:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialize with buffer capable of holding size bytes. The length of valid
|
|
|
|
|
* data is initially set to zero.
|
|
|
|
|
* <init/>
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithCapacity: (NSUInteger)capacity
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1998-10-20 14:40:05 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-27 16:18:02 +00:00
|
|
|
|
- (id) initWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
2007-12-03 18:08:58 +00:00
|
|
|
|
if ([aCoder allowsKeyedCoding])
|
2000-06-27 16:18:02 +00:00
|
|
|
|
{
|
2007-12-03 18:08:58 +00:00
|
|
|
|
const uint8_t *data;
|
2009-02-23 20:42:32 +00:00
|
|
|
|
NSUInteger l;
|
|
|
|
|
|
2000-09-27 15:26:16 +00:00
|
|
|
|
|
2007-12-03 18:08:58 +00:00
|
|
|
|
data = [aCoder decodeBytesForKey: @"NS.data"
|
2009-02-23 20:42:32 +00:00
|
|
|
|
returnedLength: &l];
|
2007-12-03 18:08:58 +00:00
|
|
|
|
self = [self initWithBytes: data length: l];
|
2000-06-27 16:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2007-12-03 18:08:58 +00:00
|
|
|
|
{
|
2009-02-23 20:42:32 +00:00
|
|
|
|
unsigned l;
|
|
|
|
|
|
2007-12-03 18:08:58 +00:00
|
|
|
|
[aCoder decodeValueOfObjCType: @encode(unsigned int) at: &l];
|
|
|
|
|
if (l)
|
|
|
|
|
{
|
|
|
|
|
void *b;
|
|
|
|
|
|
|
|
|
|
#if GS_WITH_GC
|
2009-03-10 09:35:14 +00:00
|
|
|
|
b = NSAllocateCollectable(l, 0);
|
2007-12-03 18:08:58 +00:00
|
|
|
|
#else
|
2010-03-05 09:30:18 +00:00
|
|
|
|
b = NSZoneMalloc([self zone], l);
|
2007-12-03 18:08:58 +00:00
|
|
|
|
#endif
|
|
|
|
|
if (b == 0)
|
|
|
|
|
{
|
2009-02-23 20:42:32 +00:00
|
|
|
|
NSLog(@"[NSDataMalloc -initWithCoder:] unable to get %u bytes",
|
|
|
|
|
l);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2007-12-03 18:08:58 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
[aCoder decodeArrayOfObjCType: @encode(unsigned char) count: l at: b];
|
|
|
|
|
self = [self initWithBytesNoCopy: b length: l];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
self = [self initWithBytesNoCopy: 0 length: 0];
|
|
|
|
|
}
|
2000-06-27 16:18:02 +00:00
|
|
|
|
}
|
2000-09-27 15:26:16 +00:00
|
|
|
|
return self;
|
2000-06-27 16:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialize with buffer of capacity equal to length, and with the length
|
|
|
|
|
* of valid data set to length. Data is set to zero.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithLength: (NSUInteger)length
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1998-10-20 14:40:05 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return nil;
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Adjusting Capacity
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Increases buffer length by given number of bytes, filling the new space
|
|
|
|
|
* with zeros.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) increaseLengthBy: (NSUInteger)extraLength
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1998-10-20 14:40:05 +00:00
|
|
|
|
[self setLength: [self length]+extraLength];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-20 10:22:05 +00:00
|
|
|
|
/**
|
|
|
|
|
* <p>
|
|
|
|
|
* Sets the length of the NSMutableData object.
|
|
|
|
|
* If the length is increased, the newly allocated data area
|
|
|
|
|
* is filled with zero bytes.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* This is a 'primitive' method ... you need to implement it
|
|
|
|
|
* if you write a subclass of NSMutableData.
|
|
|
|
|
* </p>
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) setLength: (NSUInteger)size
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1998-10-20 14:40:05 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-20 10:22:05 +00:00
|
|
|
|
/**
|
|
|
|
|
* <p>
|
|
|
|
|
* Returns a pointer to the data storage of the receiver.<br />
|
|
|
|
|
* Modifications to the memory pointed to by this pointer will
|
|
|
|
|
* change the contents of the object. It is important that
|
|
|
|
|
* your code should not try to modify the memory beyond the
|
|
|
|
|
* number of bytes given by the <code>-length</code> method.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* NB. if the object is released, or any method that changes its
|
|
|
|
|
* size or content is called, then the pointer previously returned
|
|
|
|
|
* by this method may cease to be valid.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* This is a 'primitive' method ... you need to implement it
|
|
|
|
|
* if you write a subclass of NSMutableData.
|
|
|
|
|
* </p>
|
|
|
|
|
*/
|
1995-04-17 20:40:59 +00:00
|
|
|
|
- (void*) mutableBytes
|
|
|
|
|
{
|
1998-10-20 14:40:05 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
2005-06-04 07:22:51 +00:00
|
|
|
|
return 0;
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Appending Data
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Appends bufferSize bytes from aBuffer to data, increasing capacity if
|
|
|
|
|
* necessary.
|
|
|
|
|
*/
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (void) appendBytes: (const void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)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
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Copies and appends data from other to data, increasing capacity if
|
|
|
|
|
* necessary.
|
|
|
|
|
*/
|
1995-04-17 20:40:59 +00:00
|
|
|
|
- (void) appendData: (NSData*)other
|
|
|
|
|
{
|
2000-06-27 16:18:02 +00:00
|
|
|
|
[self appendBytes: [other bytes] length: [other length]];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-20 10:22:05 +00:00
|
|
|
|
/**
|
|
|
|
|
* Replaces the bytes of data in the specified range with a
|
|
|
|
|
* copy of the new bytes supplied.<br />
|
|
|
|
|
* If the location of the range specified lies beyond the end
|
|
|
|
|
* of the data (<code>[self length] < range.location</code>)
|
|
|
|
|
* then a range exception is raised.<br />
|
|
|
|
|
* Otherwise, if the range specified extends beyond the end
|
|
|
|
|
* of the data, then the size of the data is increased to
|
2005-11-06 13:53:40 +00:00
|
|
|
|
* accommodate the new bytes.<br />
|
2002-08-20 10:22:05 +00:00
|
|
|
|
*/
|
1995-04-17 20:40:59 +00:00
|
|
|
|
- (void) replaceBytesInRange: (NSRange)aRange
|
|
|
|
|
withBytes: (const void*)bytes
|
|
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
|
unsigned size = [self length];
|
2001-04-10 03:27:01 +00:00
|
|
|
|
unsigned need = NSMaxRange(aRange);
|
1999-06-21 08:30:26 +00:00
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
if (aRange.location > size)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"location bad in replaceByteInRange:withBytes:"];
|
|
|
|
|
}
|
|
|
|
|
if (aRange.length > 0)
|
|
|
|
|
{
|
|
|
|
|
if (need > size)
|
|
|
|
|
{
|
|
|
|
|
[self setLength: need];
|
|
|
|
|
}
|
2002-03-11 19:52:22 +00:00
|
|
|
|
memmove([self mutableBytes] + aRange.location, bytes, aRange.length);
|
2001-04-10 03:27:01 +00:00
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
/**
|
|
|
|
|
* Replace the content of the receiver which lies in aRange with
|
|
|
|
|
* the specified length of data from the buffer pointed to by bytes.<br />
|
|
|
|
|
* The size of the receiver is adjusted to allow for the change.
|
|
|
|
|
*/
|
|
|
|
|
- (void) replaceBytesInRange: (NSRange)aRange
|
|
|
|
|
withBytes: (const void*)bytes
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)length
|
2002-08-27 12:26:17 +00:00
|
|
|
|
{
|
|
|
|
|
unsigned size = [self length];
|
|
|
|
|
unsigned end = NSMaxRange(aRange);
|
2005-02-22 11:22:44 +00:00
|
|
|
|
int shift = length - aRange.length;
|
2004-01-30 11:30:56 +00:00
|
|
|
|
unsigned need = size + shift;
|
|
|
|
|
void *buf;
|
2002-08-27 12:26:17 +00:00
|
|
|
|
|
|
|
|
|
if (aRange.location > size)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"location bad in replaceByteInRange:withBytes:"];
|
|
|
|
|
}
|
|
|
|
|
if (need > size)
|
|
|
|
|
{
|
|
|
|
|
[self setLength: need];
|
|
|
|
|
}
|
2004-01-30 11:30:56 +00:00
|
|
|
|
buf = [self mutableBytes];
|
|
|
|
|
if (shift < 0)
|
2002-08-27 12:26:17 +00:00
|
|
|
|
{
|
2004-01-30 11:30:56 +00:00
|
|
|
|
if (length > 0)
|
2002-08-27 12:26:17 +00:00
|
|
|
|
{
|
2004-01-30 11:30:56 +00:00
|
|
|
|
// Copy bytes into place.
|
|
|
|
|
memmove(buf + aRange.location, bytes, length);
|
|
|
|
|
}
|
|
|
|
|
// Fill gap
|
|
|
|
|
memmove(buf + end + shift, buf + end, size - end);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (shift > 0)
|
|
|
|
|
{
|
|
|
|
|
// Open space
|
2002-08-27 12:26:17 +00:00
|
|
|
|
memmove(buf + end + shift, buf + end, size - end);
|
|
|
|
|
}
|
|
|
|
|
if (length > 0)
|
|
|
|
|
{
|
2004-01-30 11:30:56 +00:00
|
|
|
|
// Copy bytes into place.
|
2002-08-27 12:26:17 +00:00
|
|
|
|
memmove(buf + aRange.location, bytes, length);
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-01-30 11:30:56 +00:00
|
|
|
|
if (need < size)
|
2002-08-27 12:26:17 +00:00
|
|
|
|
{
|
2004-01-30 11:30:56 +00:00
|
|
|
|
[self setLength: need];
|
2002-08-27 12:26:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set bytes in aRange to 0.
|
|
|
|
|
*/
|
1995-04-17 20:40:59 +00:00
|
|
|
|
- (void) resetBytesInRange: (NSRange)aRange
|
|
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
|
unsigned size = [self length];
|
|
|
|
|
|
|
|
|
|
GS_RANGE_CHECK(aRange, 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
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Replaces contents of buffer with contents of data's buffer, increasing
|
|
|
|
|
* or shrinking capacity to match.
|
|
|
|
|
*/
|
1998-01-19 15:20:15 +00:00
|
|
|
|
- (void) setData: (NSData*)data
|
|
|
|
|
{
|
|
|
|
|
NSRange r = NSMakeRange(0, [data length]);
|
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
[self setCapacity: r.length];
|
1998-01-19 15:20:15 +00:00
|
|
|
|
[self replaceBytesInRange: r withBytes: [data bytes]];
|
|
|
|
|
}
|
|
|
|
|
|
1995-04-17 20:40:59 +00:00
|
|
|
|
// Serializing Data
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Does not act as the name suggests. Instead, serializes length itself
|
|
|
|
|
* as an int into buffer.
|
|
|
|
|
*/
|
2001-12-17 14:31:42 +00:00
|
|
|
|
- (void) serializeAlignedBytesLength: (unsigned int)length
|
1997-09-01 21:59:51 +00:00
|
|
|
|
{
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self serializeInt: length];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-27 16:18:02 +00:00
|
|
|
|
- (void) serializeDataAt: (const void*)data
|
|
|
|
|
ofObjCType: (const char*)type
|
|
|
|
|
context: (id <NSObjCTypeSerializationCallBack>)callback
|
1997-09-01 21:59:51 +00:00
|
|
|
|
{
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (!data || !type)
|
|
|
|
|
return;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
switch (*type)
|
|
|
|
|
{
|
|
|
|
|
case _C_ID:
|
|
|
|
|
[callback serializeObjectAt: (id*)data
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
intoData: self];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_CHARPTR:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint32_t len;
|
|
|
|
|
uint32_t ni;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (!*(void**)data)
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
ni = (uint32_t)-1;
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI32ToBig(ni);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self appendBytes: (void*)&ni length: sizeof(ni)];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
2006-01-11 08:37:16 +00:00
|
|
|
|
len = (uint32_t)strlen(*(void**)data);
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI32ToBig(len);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self appendBytes: (void*)&ni length: sizeof(ni)];
|
|
|
|
|
[self appendBytes: *(void**)data length: len];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_ARY_B:
|
|
|
|
|
{
|
|
|
|
|
unsigned offset = 0;
|
|
|
|
|
unsigned size;
|
|
|
|
|
unsigned count = atoi(++type);
|
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
while (isdigit(*type))
|
|
|
|
|
{
|
|
|
|
|
type++;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
size = objc_sizeof_type(type);
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
[self serializeDataAt: (char*)data + offset
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
context: callback];
|
|
|
|
|
offset += size;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_STRUCT_B:
|
|
|
|
|
{
|
2003-04-10 16:26:09 +00:00
|
|
|
|
struct objc_struct_layout layout;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
|
2003-04-10 16:26:09 +00:00
|
|
|
|
objc_layout_structure (type, &layout);
|
|
|
|
|
while (objc_layout_structure_next_member (&layout))
|
1999-02-01 12:05:15 +00:00
|
|
|
|
{
|
2005-07-08 11:48:37 +00:00
|
|
|
|
unsigned offset;
|
|
|
|
|
unsigned align;
|
2003-04-10 16:26:09 +00:00
|
|
|
|
const char *ftype;
|
|
|
|
|
|
|
|
|
|
objc_layout_structure_get_info (&layout, &offset, &align, &ftype);
|
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self serializeDataAt: ((char*)data) + offset
|
2003-04-10 16:26:09 +00:00
|
|
|
|
ofObjCType: ftype
|
1999-02-01 12:05:15 +00:00
|
|
|
|
context: callback];
|
2003-04-10 16:26:09 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_PTR:
|
|
|
|
|
[self serializeDataAt: *(char**)data
|
|
|
|
|
ofObjCType: ++type
|
|
|
|
|
context: callback];
|
|
|
|
|
return;
|
|
|
|
|
case _C_CHR:
|
|
|
|
|
case _C_UCHR:
|
|
|
|
|
[self appendBytes: data length: sizeof(unsigned char)];
|
|
|
|
|
return;
|
|
|
|
|
case _C_SHT:
|
|
|
|
|
case _C_USHT:
|
|
|
|
|
{
|
|
|
|
|
unsigned short ns = NSSwapHostShortToBig(*(unsigned short*)data);
|
|
|
|
|
[self appendBytes: &ns length: sizeof(unsigned short)];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_INT:
|
|
|
|
|
case _C_UINT:
|
|
|
|
|
{
|
|
|
|
|
unsigned ni = NSSwapHostIntToBig(*(unsigned int*)data);
|
|
|
|
|
[self appendBytes: &ni length: sizeof(unsigned)];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_LNG:
|
|
|
|
|
case _C_ULNG:
|
|
|
|
|
{
|
|
|
|
|
unsigned long nl = NSSwapHostLongToBig(*(unsigned long*)data);
|
|
|
|
|
[self appendBytes: &nl length: sizeof(unsigned long)];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_LNG_LNG:
|
|
|
|
|
case _C_ULNG_LNG:
|
|
|
|
|
{
|
|
|
|
|
unsigned long long nl;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
nl = NSSwapHostLongLongToBig(*(unsigned long long*)data);
|
|
|
|
|
[self appendBytes: &nl length: sizeof(unsigned long long)];
|
|
|
|
|
return;
|
1998-10-20 14:40:05 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_FLT:
|
|
|
|
|
{
|
|
|
|
|
NSSwappedFloat nf = NSSwapHostFloatToBig(*(float*)data);
|
|
|
|
|
|
|
|
|
|
[self appendBytes: &nf length: sizeof(NSSwappedFloat)];
|
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_DBL:
|
|
|
|
|
{
|
|
|
|
|
NSSwappedDouble nd = NSSwapHostDoubleToBig(*(double*)data);
|
|
|
|
|
|
|
|
|
|
[self appendBytes: &nd length: sizeof(NSSwappedDouble)];
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_CLASS:
|
|
|
|
|
{
|
2010-02-22 10:13:20 +00:00
|
|
|
|
const char *name = *(Class*)data?class_getName(*(Class*)data):"";
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t ln = (uint16_t)strlen(name);
|
|
|
|
|
uint16_t ni;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI16ToBig(ln);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self appendBytes: &ni length: sizeof(ni)];
|
|
|
|
|
if (ln)
|
|
|
|
|
{
|
|
|
|
|
[self appendBytes: name length: ln];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_SEL:
|
|
|
|
|
{
|
2010-02-22 10:13:20 +00:00
|
|
|
|
const char *name = *(SEL*)data?sel_getName(*(SEL*)data):"";
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t ln = (name == 0) ? 0 : (uint16_t)strlen(name);
|
2002-02-21 13:31:13 +00:00
|
|
|
|
const char *types = *(SEL*)data?GSTypesFromSelector(*(SEL*)data):"";
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t lt = (types == 0) ? 0 : (uint16_t)strlen(types);
|
|
|
|
|
uint16_t ni;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI16ToBig(ln);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self appendBytes: &ni length: sizeof(ni)];
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI16ToBig(lt);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self appendBytes: &ni length: sizeof(ni)];
|
|
|
|
|
if (ln)
|
|
|
|
|
{
|
|
|
|
|
[self appendBytes: name length: ln];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (lt)
|
|
|
|
|
{
|
|
|
|
|
[self appendBytes: types length: lt];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
default:
|
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"Unknown type to serialize - '%s'", type];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Serialize an int into this object's data buffer, swapping it to network
|
|
|
|
|
* (big-endian) byte order first.
|
|
|
|
|
*/
|
1999-02-08 10:46:32 +00:00
|
|
|
|
- (void) serializeInt: (int)value
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1999-02-01 12:05:15 +00:00
|
|
|
|
unsigned ni = NSSwapHostIntToBig(value);
|
|
|
|
|
[self appendBytes: &ni length: sizeof(unsigned)];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Serialize an int into this object's data buffer at index (replacing
|
|
|
|
|
* anything there currently), swapping it to network (big-endian) byte order
|
|
|
|
|
* first.
|
|
|
|
|
*/
|
2001-12-17 14:31:42 +00:00
|
|
|
|
- (void) serializeInt: (int)value atIndex: (unsigned int)index
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1999-02-01 12:05:15 +00:00
|
|
|
|
unsigned ni = NSSwapHostIntToBig(value);
|
|
|
|
|
NSRange range = { index, sizeof(int) };
|
|
|
|
|
|
|
|
|
|
[self replaceBytesInRange: range withBytes: &ni];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Serialize one or more ints into this object's data buffer, swapping them to
|
|
|
|
|
* network (big-endian) byte order first.
|
|
|
|
|
*/
|
1998-10-21 11:56:58 +00:00
|
|
|
|
- (void) serializeInts: (int*)intBuffer
|
2001-12-17 14:31:42 +00:00
|
|
|
|
count: (unsigned int)numInts
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1999-02-01 12:05:15 +00:00
|
|
|
|
unsigned i;
|
|
|
|
|
SEL sel = @selector(serializeInt:);
|
|
|
|
|
IMP imp = [self methodForSelector: sel];
|
1995-04-17 20:40:59 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
for (i = 0; i < numInts; i++)
|
|
|
|
|
{
|
|
|
|
|
(*imp)(self, sel, intBuffer[i]);
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Serialize one or more ints into this object's data buffer at index
|
|
|
|
|
* (replacing anything there currently), swapping them to network (big-endian)
|
|
|
|
|
* byte order first.
|
|
|
|
|
*/
|
1998-10-21 11:56:58 +00:00
|
|
|
|
- (void) serializeInts: (int*)intBuffer
|
2001-12-17 14:31:42 +00:00
|
|
|
|
count: (unsigned int)numInts
|
|
|
|
|
atIndex: (unsigned int)index
|
1995-04-17 20:40:59 +00:00
|
|
|
|
{
|
1999-02-01 12:05:15 +00:00
|
|
|
|
unsigned i;
|
|
|
|
|
SEL sel = @selector(serializeInt:atIndex:);
|
|
|
|
|
IMP imp = [self methodForSelector: sel];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
for (i = 0; i < numInts; i++)
|
|
|
|
|
{
|
|
|
|
|
(*imp)(self, sel, intBuffer[i], index++);
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1995-04-17 20:40:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Provides some additional methods to [NSData].
|
|
|
|
|
*/
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@implementation NSMutableData (GNUstepExtensions)
|
2004-06-22 22:40:40 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* New instance with given shared memory ID.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
+ (id) dataWithShmID: (int)anID length: (NSUInteger)length
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SHMCTL
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSDataShared *d;
|
|
|
|
|
|
|
|
|
|
d = [NSMutableDataShared allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithShmID: anID length: length];
|
|
|
|
|
return AUTORELEASE(d);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#else
|
|
|
|
|
NSLog(@"[NSMutableData -dataWithSmdID:length:] no shared memory support");
|
|
|
|
|
return nil;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* New instance with given bytes in shared memory.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
+ (id) dataWithSharedBytes: (const void*)bytes length: (NSUInteger)length
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
NSData *d;
|
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SHMCTL
|
1999-07-03 19:59:44 +00:00
|
|
|
|
d = [NSMutableDataShared allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytes: bytes length: length];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#else
|
1999-07-03 19:59:44 +00:00
|
|
|
|
d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
d = [d initWithBytes: bytes length: length];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
#endif
|
1999-07-03 19:59:44 +00:00
|
|
|
|
return AUTORELEASE(d);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns current capacity of data buffer.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (NSUInteger) capacity
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sets current capacity of data buffer. Unlike [-setLength:], this will
|
|
|
|
|
* shrink the buffer if requested.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) setCapacity: (NSUInteger)newCapacity
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return shared memory ID, if using one, else -1.
|
|
|
|
|
*/
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (int) shmID
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
1998-10-23 15:48:21 +00:00
|
|
|
|
|
|
|
|
|
- (void) serializeTypeTag: (unsigned char)tag
|
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
[self serializeDataAt: (void*)&tag
|
|
|
|
|
ofObjCType: @encode(unsigned char)
|
|
|
|
|
context: nil];
|
1998-10-23 15:48:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
- (void) serializeTypeTag: (unsigned char)tag
|
2001-12-17 14:31:42 +00:00
|
|
|
|
andCrossRef: (unsigned int)xref
|
1998-10-23 15:48:21 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (xref <= 0xff)
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint8_t x = (uint8_t)xref;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
tag = (tag & ~_GSC_SIZE) | _GSC_X_1;
|
|
|
|
|
[self serializeDataAt: (void*)&tag
|
|
|
|
|
ofObjCType: @encode(unsigned char)
|
|
|
|
|
context: nil];
|
|
|
|
|
[self serializeDataAt: (void*)&x
|
2006-01-11 08:37:16 +00:00
|
|
|
|
ofObjCType: @encode(uint8_t)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
context: nil];
|
|
|
|
|
}
|
|
|
|
|
else if (xref <= 0xffff)
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t x = (uint16_t)xref;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
tag = (tag & ~_GSC_SIZE) | _GSC_X_2;
|
|
|
|
|
[self serializeDataAt: (void*)&tag
|
|
|
|
|
ofObjCType: @encode(unsigned char)
|
|
|
|
|
context: nil];
|
|
|
|
|
[self serializeDataAt: (void*)&x
|
2006-01-11 08:37:16 +00:00
|
|
|
|
ofObjCType: @encode(uint16_t)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
context: nil];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint32_t x = (uint32_t)xref;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
tag = (tag & ~_GSC_SIZE) | _GSC_X_4;
|
|
|
|
|
[self serializeDataAt: (void*)&tag
|
|
|
|
|
ofObjCType: @encode(unsigned char)
|
|
|
|
|
context: nil];
|
|
|
|
|
[self serializeDataAt: (void*)&x
|
2006-01-11 08:37:16 +00:00
|
|
|
|
ofObjCType: @encode(uint32_t)
|
1999-01-27 12:49:49 +00:00
|
|
|
|
context: nil];
|
|
|
|
|
}
|
1998-10-23 15:48:21 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
/*
|
|
|
|
|
* This is the top of the hierarchy of concrete implementations.
|
|
|
|
|
* As such, it contains efficient implementations of most methods.
|
|
|
|
|
*/
|
|
|
|
|
@implementation NSDataStatic
|
|
|
|
|
|
2000-04-14 10:38:22 +00:00
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-11-12 10:58:17 +00:00
|
|
|
|
return (NSData*)NSAllocateObject(self, 0, z);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
/* Creation and Destruction of objects. */
|
|
|
|
|
|
1998-11-12 10:58:17 +00:00
|
|
|
|
- (id) copyWithZone: (NSZone*)z
|
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
return RETAIN(self);
|
1998-11-12 10:58:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) mutableCopyWithZone: (NSZone*)z
|
|
|
|
|
{
|
|
|
|
|
return [[mutableDataMalloc allocWithZone: z]
|
2000-06-27 16:18:02 +00:00
|
|
|
|
initWithBytes: bytes length: length];
|
1998-11-12 10:58:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
1998-11-12 10:58:17 +00:00
|
|
|
|
bytes = 0;
|
|
|
|
|
length = 0;
|
|
|
|
|
[super dealloc];
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)bufferSize
|
2002-08-27 12:26:17 +00:00
|
|
|
|
freeWhenDone: (BOOL)shouldFree
|
1998-10-21 11:56:58 +00:00
|
|
|
|
{
|
2011-02-10 10:13:50 +00:00
|
|
|
|
if (aBuffer == 0 && bufferSize > 0)
|
2009-08-12 07:49:42 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"[%@-initWithBytesNoCopy:length:freeWhenDone:] called with "
|
|
|
|
|
@"length but null bytes", NSStringFromClass([self class])];
|
|
|
|
|
}
|
1998-11-12 10:58:17 +00:00
|
|
|
|
bytes = aBuffer;
|
|
|
|
|
length = bufferSize;
|
2001-04-26 23:53:22 +00:00
|
|
|
|
return self;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (Class) classForCoder
|
|
|
|
|
{
|
2007-10-03 05:36:07 +00:00
|
|
|
|
return NSDataAbstract;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
/* Basic methods */
|
|
|
|
|
|
|
|
|
|
- (const void*) bytes
|
|
|
|
|
{
|
1998-11-12 10:58:17 +00:00
|
|
|
|
return bytes;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) getBytes: (void*)buffer
|
|
|
|
|
range: (NSRange)aRange
|
|
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
|
GS_RANGE_CHECK(aRange, length);
|
|
|
|
|
memcpy(buffer, bytes + aRange.location, aRange.length);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (NSUInteger) length
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-11-12 10:58:17 +00:00
|
|
|
|
return length;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-22 20:20:31 +00:00
|
|
|
|
static inline void
|
|
|
|
|
getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
|
|
|
|
{
|
1998-11-12 10:58:17 +00:00
|
|
|
|
if (*pos > limit || len > limit || len+*pos > limit)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"Range: (%u, %u) Size: %d",
|
1998-10-22 20:20:31 +00:00
|
|
|
|
*pos, len, limit];
|
|
|
|
|
}
|
1998-11-12 10:58:17 +00:00
|
|
|
|
memcpy(dst, src + *pos, len);
|
|
|
|
|
*pos += len;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-08 10:46:32 +00:00
|
|
|
|
- (void) deserializeDataAt: (void*)data
|
|
|
|
|
ofObjCType: (const char*)type
|
2001-12-17 14:31:42 +00:00
|
|
|
|
atCursor: (unsigned int*)cursor
|
1999-02-08 10:46:32 +00:00
|
|
|
|
context: (id <NSObjCTypeSerializationCallBack>)callback
|
1998-10-22 20:20:31 +00:00
|
|
|
|
{
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (data == 0 || type == 0)
|
|
|
|
|
{
|
|
|
|
|
if (data == 0)
|
|
|
|
|
{
|
2002-08-20 15:07:58 +00:00
|
|
|
|
NSLog(@"attempt to deserialize to a null pointer");
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (type == 0)
|
|
|
|
|
{
|
2002-08-20 15:07:58 +00:00
|
|
|
|
NSLog(@"attempt to deserialize with a null type encoding");
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
switch (*type)
|
|
|
|
|
{
|
|
|
|
|
case _C_ID:
|
|
|
|
|
{
|
|
|
|
|
[callback deserializeObjectAt: data
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
fromData: self
|
|
|
|
|
atCursor: cursor];
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_CHARPTR:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
int32_t len;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self deserializeBytes: &len
|
|
|
|
|
length: sizeof(len)
|
|
|
|
|
atCursor: cursor];
|
1999-02-08 10:46:32 +00:00
|
|
|
|
len = GSSwapBigI32ToHost(len);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (len == -1)
|
|
|
|
|
{
|
2005-06-04 07:22:51 +00:00
|
|
|
|
*(const char**)data = 0;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
*(char**)data = (char*)NSAllocateCollectable(len+1, 0);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
#else
|
2009-03-10 09:35:14 +00:00
|
|
|
|
*(char**)data = (char*)NSZoneMalloc(NSDefaultMallocZone(), len+1);
|
1999-07-03 19:59:44 +00:00
|
|
|
|
#endif
|
2002-10-07 13:46:22 +00:00
|
|
|
|
if (*(char**)data == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
|
format: @"out of memory to deserialize bytes"];
|
|
|
|
|
}
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes(*(void**)data, bytes, len, length, cursor);
|
|
|
|
|
(*(char**)data)[len] = '\0';
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_ARY_B:
|
|
|
|
|
{
|
|
|
|
|
unsigned offset = 0;
|
|
|
|
|
unsigned size;
|
|
|
|
|
unsigned count = atoi(++type);
|
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
while (isdigit(*type))
|
|
|
|
|
{
|
|
|
|
|
type++;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
size = objc_sizeof_type(type);
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
[self deserializeDataAt: (char*)data + offset
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: callback];
|
|
|
|
|
offset += size;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_STRUCT_B:
|
|
|
|
|
{
|
2003-04-10 16:26:09 +00:00
|
|
|
|
struct objc_struct_layout layout;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
2003-04-10 16:26:09 +00:00
|
|
|
|
objc_layout_structure (type, &layout);
|
|
|
|
|
while (objc_layout_structure_next_member (&layout))
|
1999-02-01 12:05:15 +00:00
|
|
|
|
{
|
2005-07-08 11:48:37 +00:00
|
|
|
|
unsigned offset;
|
|
|
|
|
unsigned align;
|
2003-04-10 16:26:09 +00:00
|
|
|
|
const char *ftype;
|
|
|
|
|
|
|
|
|
|
objc_layout_structure_get_info (&layout, &offset, &align, &ftype);
|
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self deserializeDataAt: ((char*)data) + offset
|
2003-04-10 16:26:09 +00:00
|
|
|
|
ofObjCType: ftype
|
1999-02-01 12:05:15 +00:00
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: callback];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_PTR:
|
|
|
|
|
{
|
|
|
|
|
unsigned len = objc_sizeof_type(++type);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
*(char**)data = (char*)NSAllocateCollectable(len, 0);
|
2000-07-02 18:57:05 +00:00
|
|
|
|
#else
|
2009-03-10 09:35:14 +00:00
|
|
|
|
*(char**)data = (char*)NSZoneMalloc(NSDefaultMallocZone(), len);
|
|
|
|
|
#endif
|
2002-10-07 13:46:22 +00:00
|
|
|
|
if (*(char**)data == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
|
format: @"out of memory to deserialize bytes"];
|
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self deserializeDataAt: *(char**)data
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
atCursor: cursor
|
|
|
|
|
context: callback];
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_CHR:
|
|
|
|
|
case _C_UCHR:
|
|
|
|
|
{
|
|
|
|
|
getBytes(data, bytes, sizeof(unsigned char), length, cursor);
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_SHT:
|
|
|
|
|
case _C_USHT:
|
|
|
|
|
{
|
|
|
|
|
unsigned short ns;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes((void*)&ns, bytes, sizeof(ns), length, cursor);
|
|
|
|
|
*(unsigned short*)data = NSSwapBigShortToHost(ns);
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_INT:
|
|
|
|
|
case _C_UINT:
|
|
|
|
|
{
|
|
|
|
|
unsigned ni;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes((void*)&ni, bytes, sizeof(ni), length, cursor);
|
|
|
|
|
*(unsigned*)data = NSSwapBigIntToHost(ni);
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_LNG:
|
|
|
|
|
case _C_ULNG:
|
|
|
|
|
{
|
|
|
|
|
unsigned long nl;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes((void*)&nl, bytes, sizeof(nl), length, cursor);
|
|
|
|
|
*(unsigned long*)data = NSSwapBigLongToHost(nl);
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_LNG_LNG:
|
|
|
|
|
case _C_ULNG_LNG:
|
|
|
|
|
{
|
|
|
|
|
unsigned long long nl;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes((void*)&nl, bytes, sizeof(nl), length, cursor);
|
|
|
|
|
*(unsigned long long*)data = NSSwapBigLongLongToHost(nl);
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_FLT:
|
|
|
|
|
{
|
|
|
|
|
NSSwappedFloat nf;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes((void*)&nf, bytes, sizeof(nf), length, cursor);
|
|
|
|
|
*(float*)data = NSSwapBigFloatToHost(nf);
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_DBL:
|
|
|
|
|
{
|
|
|
|
|
NSSwappedDouble nd;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes((void*)&nd, bytes, sizeof(nd), length, cursor);
|
|
|
|
|
*(double*)data = NSSwapBigDoubleToHost(nd);
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_CLASS:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t ni;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes((void*)&ni, bytes, sizeof(ni), length, cursor);
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapBigI16ToHost(ni);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (ni == 0)
|
|
|
|
|
{
|
|
|
|
|
*(Class*)data = 0;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char name[ni+1];
|
|
|
|
|
Class c;
|
|
|
|
|
|
|
|
|
|
getBytes((void*)name, bytes, ni, length, cursor);
|
|
|
|
|
name[ni] = '\0';
|
2010-02-22 10:13:20 +00:00
|
|
|
|
c = objc_lookUpClass(name);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (c == 0)
|
|
|
|
|
{
|
2002-02-21 13:31:13 +00:00
|
|
|
|
NSLog(@"[%s %s] can't find class - %s",
|
2010-02-22 10:13:20 +00:00
|
|
|
|
class_getName([self class]),
|
|
|
|
|
sel_getName(_cmd), name);
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
*(Class*)data = c;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_SEL:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t ln;
|
|
|
|
|
uint16_t lt;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
|
|
|
|
|
getBytes((void*)&ln, bytes, sizeof(ln), length, cursor);
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ln = GSSwapBigI16ToHost(ln);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
getBytes((void*)<, bytes, sizeof(lt), length, cursor);
|
1999-02-08 10:46:32 +00:00
|
|
|
|
lt = GSSwapBigI16ToHost(lt);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (ln == 0)
|
|
|
|
|
{
|
|
|
|
|
*(SEL*)data = 0;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char name[ln+1];
|
|
|
|
|
char types[lt+1];
|
|
|
|
|
SEL sel;
|
|
|
|
|
|
|
|
|
|
getBytes((void*)name, bytes, ln, length, cursor);
|
|
|
|
|
name[ln] = '\0';
|
|
|
|
|
getBytes((void*)types, bytes, lt, length, cursor);
|
|
|
|
|
types[lt] = '\0';
|
|
|
|
|
|
|
|
|
|
if (lt)
|
|
|
|
|
{
|
2011-02-20 07:58:11 +00:00
|
|
|
|
sel = GSSelectorFromNameAndTypes(name, types);
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2010-09-09 16:30:10 +00:00
|
|
|
|
sel = sel_registerName(name);
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (sel == 0)
|
|
|
|
|
{
|
2000-10-26 14:12:44 +00:00
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"can't make sel with name '%s' "
|
|
|
|
|
@"and types '%s'", name, types];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
*(SEL*)data = sel;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
default:
|
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"Unknown type to deserialize - '%s'", type];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
- (void) deserializeTypeTag: (unsigned char*)tag
|
|
|
|
|
andCrossRef: (unsigned int*)ref
|
2001-12-17 14:31:42 +00:00
|
|
|
|
atCursor: (unsigned int*)cursor
|
1998-10-23 15:48:21 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (*cursor >= length)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"Range: (%u, 1) Size: %d", *cursor, length];
|
|
|
|
|
}
|
|
|
|
|
*tag = *((unsigned char*)bytes + (*cursor)++);
|
|
|
|
|
if (*tag & _GSC_MAYX)
|
|
|
|
|
{
|
|
|
|
|
switch (*tag & _GSC_SIZE)
|
|
|
|
|
{
|
|
|
|
|
case _GSC_X_0:
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case _GSC_X_1:
|
|
|
|
|
{
|
|
|
|
|
if (*cursor >= length)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"Range: (%u, 1) Size: %d",
|
|
|
|
|
*cursor, length];
|
|
|
|
|
}
|
|
|
|
|
*ref = (unsigned int)*((unsigned char*)bytes + (*cursor)++);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case _GSC_X_2:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t x;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
if (*cursor >= length-1)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"Range: (%u, 1) Size: %d",
|
|
|
|
|
*cursor, length];
|
|
|
|
|
}
|
2000-05-23 16:26:40 +00:00
|
|
|
|
#if NEED_WORD_ALIGNMENT
|
2006-01-11 08:37:16 +00:00
|
|
|
|
if ((*cursor % __alignof__(uint16_t)) != 0)
|
2000-05-03 03:14:14 +00:00
|
|
|
|
memcpy(&x, (bytes + *cursor), 2);
|
|
|
|
|
else
|
|
|
|
|
#endif
|
2006-01-11 08:37:16 +00:00
|
|
|
|
x = *(uint16_t*)(bytes + *cursor);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
*cursor += 2;
|
1999-02-08 10:46:32 +00:00
|
|
|
|
*ref = (unsigned int)GSSwapBigI16ToHost(x);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint32_t x;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
if (*cursor >= length-3)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
|
format: @"Range: (%u, 1) Size: %d",
|
|
|
|
|
*cursor, length];
|
|
|
|
|
}
|
2000-05-23 16:26:40 +00:00
|
|
|
|
#if NEED_WORD_ALIGNMENT
|
2006-01-11 08:37:16 +00:00
|
|
|
|
if ((*cursor % __alignof__(uint32_t)) != 0)
|
2000-05-03 03:14:14 +00:00
|
|
|
|
memcpy(&x, (bytes + *cursor), 4);
|
|
|
|
|
else
|
|
|
|
|
#endif
|
2006-01-11 08:37:16 +00:00
|
|
|
|
x = *(uint32_t*)(bytes + *cursor);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
*cursor += 4;
|
1999-02-08 10:46:32 +00:00
|
|
|
|
*ref = (unsigned int)GSSwapBigI32ToHost(x);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-23 15:48:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
@end
|
|
|
|
|
|
1998-10-23 15:48:21 +00:00
|
|
|
|
|
2002-08-27 12:26:17 +00:00
|
|
|
|
@implementation NSDataEmpty
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2006-06-04 06:42:10 +00:00
|
|
|
|
GSNOSUPERDEALLOC;
|
2002-08-27 12:26:17 +00:00
|
|
|
|
}
|
1998-10-21 11:56:58 +00:00
|
|
|
|
@end
|
2002-08-27 12:26:17 +00:00
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
|
|
|
|
|
@implementation NSDataMalloc
|
|
|
|
|
|
1998-11-12 10:58:17 +00:00
|
|
|
|
- (id) copyWithZone: (NSZone*)z
|
|
|
|
|
{
|
1999-05-06 14:42:26 +00:00
|
|
|
|
if (NSShouldRetainWithZone(self, z))
|
1999-07-03 19:59:44 +00:00
|
|
|
|
return RETAIN(self);
|
1999-05-06 14:42:26 +00:00
|
|
|
|
else
|
|
|
|
|
return [[dataMalloc allocWithZone: z]
|
|
|
|
|
initWithBytes: bytes length: length];
|
1998-11-12 10:58:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
- (void) dealloc
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2000-09-27 15:26:16 +00:00
|
|
|
|
if (bytes != 0)
|
1998-11-12 10:58:17 +00:00
|
|
|
|
{
|
2000-09-27 15:26:16 +00:00
|
|
|
|
NSZoneFree(NSZoneFromPointer(bytes), bytes);
|
1998-11-12 10:58:17 +00:00
|
|
|
|
bytes = 0;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1998-11-12 10:58:17 +00:00
|
|
|
|
[super dealloc];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)bufferSize
|
2002-08-27 12:26:17 +00:00
|
|
|
|
freeWhenDone: (BOOL)shouldFree
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (aBuffer == 0 && bufferSize > 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"[%@-initWithBytesNoCopy:length:freeWhenDone:] called with "
|
|
|
|
|
@"length but null bytes", NSStringFromClass([self class])];
|
|
|
|
|
}
|
2002-08-27 12:26:17 +00:00
|
|
|
|
if (shouldFree == NO)
|
|
|
|
|
{
|
2011-02-20 16:21:43 +00:00
|
|
|
|
GSClassSwizzle(self, dataStatic);
|
2009-04-15 08:03:19 +00:00
|
|
|
|
}
|
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
else if (aBuffer != 0 && GSPrivateIsCollectable(aBuffer) == NO)
|
|
|
|
|
{
|
2011-02-20 16:21:43 +00:00
|
|
|
|
GSClassSwizzle(self, dataFinalized);
|
2002-08-27 12:26:17 +00:00
|
|
|
|
}
|
2009-04-15 08:03:19 +00:00
|
|
|
|
#endif
|
1998-11-12 10:58:17 +00:00
|
|
|
|
bytes = aBuffer;
|
2000-09-27 15:26:16 +00:00
|
|
|
|
length = bufferSize;
|
1998-11-12 10:58:17 +00:00
|
|
|
|
return self;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
2009-04-15 08:03:19 +00:00
|
|
|
|
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#if GS_WITH_GC
|
2009-04-15 08:03:19 +00:00
|
|
|
|
@implementation NSDataFinalized
|
|
|
|
|
- (void) finalize
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), bytes);
|
|
|
|
|
[super finalize];
|
|
|
|
|
}
|
|
|
|
|
@end
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#endif
|
2009-04-15 08:03:19 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_MMAP
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@implementation NSDataMappedFile
|
2000-04-14 10:38:22 +00:00
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
return (NSData*)NSAllocateObject([NSDataMappedFile class], 0, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
2009-04-15 08:03:19 +00:00
|
|
|
|
{
|
|
|
|
|
[self finalize];
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) finalize
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2000-09-27 15:26:16 +00:00
|
|
|
|
if (bytes != 0)
|
1998-11-12 10:58:17 +00:00
|
|
|
|
{
|
|
|
|
|
munmap(bytes, length);
|
|
|
|
|
bytes = 0;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
2009-04-15 08:03:19 +00:00
|
|
|
|
[super finalize];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialize with data pointing to contents of file at path. Bytes are
|
|
|
|
|
* only "swapped in" as needed. File should not be moved or deleted for
|
|
|
|
|
* the life of this object.
|
|
|
|
|
*/
|
1997-09-29 14:39:53 +00:00
|
|
|
|
- (id) initWithContentsOfMappedFile: (NSString*)path
|
|
|
|
|
{
|
2011-02-11 14:31:25 +00:00
|
|
|
|
off_t off;
|
2005-06-04 07:22:51 +00:00
|
|
|
|
int fd;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2005-06-04 07:22:51 +00:00
|
|
|
|
const unichar *thePath = (const unichar*)[path filesystemRepresentation];
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#else
|
2005-06-04 07:22:51 +00:00
|
|
|
|
const char *thePath = [path fileSystemRepresentation];
|
2005-02-22 11:22:44 +00:00
|
|
|
|
#endif
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
2005-06-04 07:22:51 +00:00
|
|
|
|
if (thePath == 0)
|
|
|
|
|
{
|
|
|
|
|
NSWarnMLog(@"Open (%@) attempt failed - bad path", path);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2005-06-04 07:22:51 +00:00
|
|
|
|
fd = _wopen(thePath, _O_RDONLY);
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#else
|
2005-06-04 07:22:51 +00:00
|
|
|
|
fd = open(thePath, O_RDONLY);
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#endif
|
2005-06-04 07:22:51 +00:00
|
|
|
|
if (fd < 0)
|
|
|
|
|
{
|
2006-10-20 10:56:27 +00:00
|
|
|
|
NSWarnMLog(@"unable to open %@ - %@", path, [NSError _last]);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
/* Find size of file to be mapped. */
|
2011-02-11 14:31:25 +00:00
|
|
|
|
off = lseek(fd, 0, SEEK_END);
|
|
|
|
|
if (off < 0)
|
2005-06-04 07:22:51 +00:00
|
|
|
|
{
|
2006-10-20 10:56:27 +00:00
|
|
|
|
NSWarnMLog(@"unable to seek to eof %@ - %@", path, [NSError _last]);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
close(fd);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
2011-02-11 14:31:25 +00:00
|
|
|
|
length = off;
|
2005-06-04 07:22:51 +00:00
|
|
|
|
/* Position at start of file. */
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) != 0)
|
|
|
|
|
{
|
2006-10-20 10:56:27 +00:00
|
|
|
|
NSWarnMLog(@"unable to seek to sof %@ - %@", path, [NSError _last]);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
close(fd);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
bytes = mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
|
|
|
|
|
if (bytes == MAP_FAILED)
|
|
|
|
|
{
|
2006-10-20 10:56:27 +00:00
|
|
|
|
NSWarnMLog(@"mapping failed for %s - %@", path, [NSError _last]);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
close(fd);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
self = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
|
|
|
|
self = [self initWithContentsOfFile: path];
|
|
|
|
|
}
|
|
|
|
|
close(fd);
|
|
|
|
|
return self;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
#endif /* HAVE_MMAP */
|
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SHMCTL
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@implementation NSDataShared
|
2000-04-14 10:38:22 +00:00
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
return (NSData*)NSAllocateObject([NSDataShared class], 0, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2000-09-27 15:26:16 +00:00
|
|
|
|
if (bytes != 0)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1997-10-28 14:34:49 +00:00
|
|
|
|
struct shmid_ds buf;
|
|
|
|
|
|
|
|
|
|
if (shmctl(shmid, IPC_STAT, &buf) < 0)
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSLog(@"[NSDataShared -dealloc] shared memory control failed - %@",
|
2006-10-20 10:56:27 +00:00
|
|
|
|
[NSError _last]);
|
1997-10-28 14:34:49 +00:00
|
|
|
|
else if (buf.shm_nattch == 1)
|
|
|
|
|
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSLog(@"[NSDataShared -dealloc] shared memory delete failed - %@",
|
2006-10-20 10:56:27 +00:00
|
|
|
|
[NSError _last]);
|
1997-10-28 14:34:49 +00:00
|
|
|
|
if (shmdt(bytes) < 0)
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSLog(@"[NSDataShared -dealloc] shared memory detach failed - %@",
|
2006-10-20 10:56:27 +00:00
|
|
|
|
[NSError _last]);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = 0;
|
|
|
|
|
length = 0;
|
|
|
|
|
shmid = -1;
|
|
|
|
|
}
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithBytes: (const void*)aBuffer length: (NSUInteger)bufferSize
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
shmid = -1;
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (bufferSize > 0)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (aBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"[%@-initWithBytes:length:] called with "
|
|
|
|
|
@"length but null bytes", NSStringFromClass([self class])];
|
|
|
|
|
}
|
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? */
|
|
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSLog(@"[-initWithBytes:length:] shared mem get failed for %u - %@",
|
2006-10-20 10:56:27 +00:00
|
|
|
|
bufferSize, [NSError _last]);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
1999-05-06 14:42:26 +00:00
|
|
|
|
self = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [self initWithBytes: aBuffer length: bufferSize];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bytes = shmat(shmid, 0, 0);
|
|
|
|
|
if (bytes == (void*)-1)
|
|
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSLog(@"[-initWithBytes:length:] shared mem attach failed for %u - %@",
|
2006-10-20 10:56:27 +00:00
|
|
|
|
bufferSize, [NSError _last]);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = 0;
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
1999-05-06 14:42:26 +00:00
|
|
|
|
self = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return [self initWithBytes: aBuffer length: bufferSize];
|
|
|
|
|
}
|
|
|
|
|
length = bufferSize;
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithShmID: (int)anId length: (NSUInteger)bufferSize
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
struct shmid_ds buf;
|
|
|
|
|
|
|
|
|
|
shmid = anId;
|
|
|
|
|
if (shmctl(shmid, IPC_STAT, &buf) < 0)
|
|
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSLog(@"[NSDataShared -initWithShmID:length:] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"control failed - %@", [NSError _last]);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self); /* Unable to access memory. */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
if (buf.shm_segsz < bufferSize)
|
|
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSLog(@"[NSDataShared -initWithShmID:length:] shared memory "
|
|
|
|
|
@"segment too small");
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self); /* Memory segment too small. */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
bytes = shmat(shmid, 0, 0);
|
|
|
|
|
if (bytes == (void*)-1)
|
|
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
|
NSLog(@"[NSDataShared -initWithShmID:length:] shared memory "
|
2010-02-22 10:48:10 +00:00
|
|
|
|
@"attach failed - %@", [NSError _last]);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = 0;
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self); /* Unable to attach to memory. */
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
length = bufferSize;
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (int) shmID
|
|
|
|
|
{
|
|
|
|
|
return shmid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
#endif /* HAVE_SHMCTL */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation NSMutableDataMalloc
|
1998-10-21 11:56:58 +00:00
|
|
|
|
+ (void) initialize
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
if (self == [NSMutableDataMalloc class])
|
|
|
|
|
{
|
2002-11-27 12:52:29 +00:00
|
|
|
|
GSObjCAddClassBehavior(self, [NSDataMalloc class]);
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-14 10:38:22 +00:00
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1998-10-21 11:56:58 +00:00
|
|
|
|
return (NSData*)NSAllocateObject(mutableDataMalloc, 0, z);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (Class) classForCoder
|
|
|
|
|
{
|
2007-10-03 05:36:07 +00:00
|
|
|
|
return NSMutableDataAbstract;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-11-12 10:58:17 +00:00
|
|
|
|
- (id) copyWithZone: (NSZone*)z
|
|
|
|
|
{
|
|
|
|
|
return [[dataMalloc allocWithZone: z]
|
1999-09-29 20:15:17 +00:00
|
|
|
|
initWithBytes: bytes length: length];
|
1998-11-12 10:58:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-01 15:51:34 +00:00
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if !GS_WITH_GC
|
2001-06-01 15:51:34 +00:00
|
|
|
|
if (bytes != 0)
|
|
|
|
|
{
|
2002-08-27 12:26:17 +00:00
|
|
|
|
if (zone != 0)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(zone, bytes);
|
|
|
|
|
}
|
2001-06-01 15:51:34 +00:00
|
|
|
|
bytes = 0;
|
|
|
|
|
}
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#endif
|
2001-06-01 15:51:34 +00:00
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithBytes: (const void*)aBuffer length: (NSUInteger)bufferSize
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
self = [self initWithCapacity: bufferSize];
|
|
|
|
|
if (self)
|
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (bufferSize > 0)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (aBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"[%@-initWithBytes:length:] called with "
|
|
|
|
|
@"length but null bytes", NSStringFromClass([self class])];
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
length = bufferSize;
|
2009-08-12 07:49:42 +00:00
|
|
|
|
memcpy(bytes, aBuffer, length);
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithBytesNoCopy: (void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)bufferSize
|
2002-08-27 12:26:17 +00:00
|
|
|
|
freeWhenDone: (BOOL)shouldFree
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
if (aBuffer == 0)
|
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (bufferSize > 0)
|
1999-09-29 20:15:17 +00:00
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"[%@-initWithBytesNoCopy:length:freeWhenDone:] called with "
|
|
|
|
|
@"length but null bytes", NSStringFromClass([self class])];
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
2009-08-12 07:49:42 +00:00
|
|
|
|
self = [self initWithCapacity: bufferSize];
|
|
|
|
|
[self setLength: 0];
|
1999-09-29 20:15:17 +00:00
|
|
|
|
return self;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
2009-04-15 08:03:19 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
if (shouldFree == YES && GSPrivateIsCollectable(aBuffer) == NO)
|
|
|
|
|
{
|
2011-02-20 16:21:43 +00:00
|
|
|
|
GSClassSwizzle(self, mutableDataFinalized);
|
2009-04-15 08:03:19 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
1999-09-29 20:15:17 +00:00
|
|
|
|
self = [self initWithCapacity: 0];
|
|
|
|
|
if (self)
|
|
|
|
|
{
|
2009-04-15 08:03:19 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
owned = shouldFree; // Free memory on finalisation.
|
|
|
|
|
#else
|
2009-08-11 14:03:47 +00:00
|
|
|
|
if (shouldFree == NO)
|
2002-08-27 12:26:17 +00:00
|
|
|
|
{
|
|
|
|
|
zone = 0; // Don't free this memory.
|
|
|
|
|
}
|
2009-08-11 13:36:39 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
zone = NSZoneFromPointer(aBuffer);
|
|
|
|
|
}
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#endif
|
1999-09-29 20:15:17 +00:00
|
|
|
|
bytes = aBuffer;
|
|
|
|
|
length = bufferSize;
|
|
|
|
|
capacity = bufferSize;
|
|
|
|
|
growth = capacity/2;
|
|
|
|
|
if (growth == 0)
|
|
|
|
|
{
|
|
|
|
|
growth = 1;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-09-29 20:15:17 +00:00
|
|
|
|
return self;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
// THIS IS THE DESIGNATED INITIALISER
|
|
|
|
|
/**
|
|
|
|
|
* Initialize with buffer capable of holding size bytes.
|
|
|
|
|
* <init/>
|
1998-10-21 11:56:58 +00:00
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithCapacity: (NSUInteger)size
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
if (size)
|
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
bytes = NSAllocateCollectable(size, 0);
|
|
|
|
|
#else
|
2010-03-05 09:30:18 +00:00
|
|
|
|
zone = [self zone];
|
1999-09-29 20:15:17 +00:00
|
|
|
|
bytes = NSZoneMalloc(zone, size);
|
2009-03-10 09:35:14 +00:00
|
|
|
|
#endif
|
1999-09-29 20:15:17 +00:00
|
|
|
|
if (bytes == 0)
|
|
|
|
|
{
|
2002-08-27 12:26:17 +00:00
|
|
|
|
NSLog(@"[NSMutableDataMalloc -initWithCapacity:] out of memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"for %u bytes - %@", size, [NSError _last]);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
1999-09-29 20:15:17 +00:00
|
|
|
|
return nil;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1999-09-29 20:15:17 +00:00
|
|
|
|
capacity = size;
|
|
|
|
|
growth = capacity/2;
|
|
|
|
|
if (growth == 0)
|
|
|
|
|
{
|
|
|
|
|
growth = 1;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-09-29 20:15:17 +00:00
|
|
|
|
length = 0;
|
1998-10-15 05:03:16 +00:00
|
|
|
|
|
1999-09-29 20:15:17 +00:00
|
|
|
|
return self;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialize with buffer capable of holding size bytes. Buffer is zeroed
|
|
|
|
|
* out.
|
|
|
|
|
*/
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithLength: (NSUInteger)size
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
self = [self initWithCapacity: size];
|
|
|
|
|
if (self)
|
|
|
|
|
{
|
|
|
|
|
memset(bytes, '\0', size);
|
|
|
|
|
length = size;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
1999-09-29 20:15:17 +00:00
|
|
|
|
return self;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithContentsOfMappedFile: (NSString *)path
|
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
return [self initWithContentsOfFile: path];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
- (void) appendBytes: (const void*)aBuffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
length: (NSUInteger)bufferSize
|
1998-10-21 11:56:58 +00:00
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (bufferSize > 0)
|
1999-09-29 20:15:17 +00:00
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
unsigned oldLength = length;
|
|
|
|
|
unsigned minimum = length + bufferSize;
|
|
|
|
|
|
|
|
|
|
if (aBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"[%@-appendBytes:length:] called with "
|
|
|
|
|
@"length but null bytes", NSStringFromClass([self class])];
|
|
|
|
|
}
|
|
|
|
|
if (minimum > capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: minimum];
|
|
|
|
|
}
|
|
|
|
|
memcpy(bytes + oldLength, aBuffer, bufferSize);
|
|
|
|
|
length = minimum;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (NSUInteger) capacity
|
1998-10-21 11:56:58 +00:00
|
|
|
|
{
|
|
|
|
|
return capacity;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) _grow: (NSUInteger)minimum
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
if (minimum > capacity)
|
|
|
|
|
{
|
|
|
|
|
unsigned nextCapacity = capacity + growth;
|
|
|
|
|
unsigned nextGrowth = capacity ? capacity : 1;
|
|
|
|
|
|
|
|
|
|
while (nextCapacity < minimum)
|
|
|
|
|
{
|
|
|
|
|
unsigned tmp = nextCapacity + nextGrowth;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
|
1999-09-29 20:15:17 +00:00
|
|
|
|
nextGrowth = nextCapacity;
|
|
|
|
|
nextCapacity = tmp;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-09-29 20:15:17 +00:00
|
|
|
|
[self setCapacity: nextCapacity];
|
|
|
|
|
growth = nextGrowth;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void*) mutableBytes
|
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
return bytes;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
- (void) replaceBytesInRange: (NSRange)aRange
|
|
|
|
|
withBytes: (const void*)moreBytes
|
|
|
|
|
{
|
2001-04-10 03:27:01 +00:00
|
|
|
|
unsigned need = NSMaxRange(aRange);
|
|
|
|
|
|
2001-04-20 17:02:49 +00:00
|
|
|
|
if (aRange.location > length)
|
2001-04-10 03:27:01 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSRangeException
|
2009-08-12 07:49:42 +00:00
|
|
|
|
format: @"location bad in replaceBytesInRange:withBytes:"];
|
2001-04-10 03:27:01 +00:00
|
|
|
|
}
|
|
|
|
|
if (aRange.length > 0)
|
|
|
|
|
{
|
2009-08-12 07:49:42 +00:00
|
|
|
|
if (moreBytes == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"[%@-replaceBytesInRange:withBytes:] called with "
|
|
|
|
|
@"range but null bytes", NSStringFromClass([self class])];
|
|
|
|
|
}
|
2001-04-10 03:27:01 +00:00
|
|
|
|
if (need > length)
|
|
|
|
|
{
|
|
|
|
|
[self setCapacity: need];
|
|
|
|
|
length = need;
|
|
|
|
|
}
|
|
|
|
|
memcpy(bytes + aRange.location, moreBytes, aRange.length);
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-10-21 11:56:58 +00:00
|
|
|
|
- (void) serializeDataAt: (const void*)data
|
|
|
|
|
ofObjCType: (const char*)type
|
|
|
|
|
context: (id <NSObjCTypeSerializationCallBack>)callback
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (data == 0 || type == 0)
|
|
|
|
|
{
|
|
|
|
|
if (data == 0)
|
|
|
|
|
{
|
2002-08-20 15:07:58 +00:00
|
|
|
|
NSLog(@"attempt to serialize from a null pointer");
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (type == 0)
|
|
|
|
|
{
|
2002-08-20 15:07:58 +00:00
|
|
|
|
NSLog(@"attempt to serialize with a null type encoding");
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
switch (*type)
|
|
|
|
|
{
|
|
|
|
|
case _C_ID:
|
|
|
|
|
[callback serializeObjectAt: (id*)data
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
intoData: self];
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case _C_CHARPTR:
|
|
|
|
|
{
|
|
|
|
|
unsigned len;
|
2006-01-11 08:37:16 +00:00
|
|
|
|
int32_t ni;
|
|
|
|
|
uint32_t minimum;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
|
|
|
|
|
if (!*(void**)data)
|
|
|
|
|
{
|
|
|
|
|
ni = -1;
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI32ToBig(ni);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self appendBytes: (void*)&len length: sizeof(len)];
|
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
len = strlen(*(void**)data);
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI32ToBig(len);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
minimum = length + len + sizeof(ni);
|
|
|
|
|
if (minimum > capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: minimum];
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
memcpy(bytes+length, &ni, sizeof(ni));
|
|
|
|
|
length += sizeof(ni);
|
|
|
|
|
if (len)
|
|
|
|
|
{
|
|
|
|
|
memcpy(bytes+length, *(void**)data, len);
|
|
|
|
|
length += len;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_ARY_B:
|
|
|
|
|
{
|
|
|
|
|
unsigned offset = 0;
|
|
|
|
|
unsigned size;
|
|
|
|
|
unsigned count = atoi(++type);
|
|
|
|
|
unsigned i;
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint32_t minimum;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
|
|
|
|
|
while (isdigit(*type))
|
|
|
|
|
{
|
|
|
|
|
type++;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
size = objc_sizeof_type(type);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Serialized objects are going to take up at least as much
|
|
|
|
|
* space as the originals, so we can calculate a minimum space
|
|
|
|
|
* we are going to need and make sure our buffer is big enough.
|
|
|
|
|
*/
|
|
|
|
|
minimum = length + size*count;
|
|
|
|
|
if (minimum > capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: minimum];
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
[self serializeDataAt: (char*)data + offset
|
|
|
|
|
ofObjCType: type
|
|
|
|
|
context: callback];
|
|
|
|
|
offset += size;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case _C_STRUCT_B:
|
|
|
|
|
{
|
2003-04-10 16:26:09 +00:00
|
|
|
|
struct objc_struct_layout layout;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
|
2003-04-10 16:26:09 +00:00
|
|
|
|
objc_layout_structure (type, &layout);
|
|
|
|
|
while (objc_layout_structure_next_member (&layout))
|
1999-02-01 12:05:15 +00:00
|
|
|
|
{
|
2005-07-08 11:48:37 +00:00
|
|
|
|
unsigned offset;
|
|
|
|
|
unsigned align;
|
2003-04-10 16:26:09 +00:00
|
|
|
|
const char *ftype;
|
|
|
|
|
|
|
|
|
|
objc_layout_structure_get_info (&layout, &offset, &align, &ftype);
|
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
[self serializeDataAt: ((char*)data) + offset
|
2003-04-10 16:26:09 +00:00
|
|
|
|
ofObjCType: ftype
|
1999-02-01 12:05:15 +00:00
|
|
|
|
context: callback];
|
|
|
|
|
}
|
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_PTR:
|
|
|
|
|
[self serializeDataAt: *(char**)data
|
|
|
|
|
ofObjCType: ++type
|
|
|
|
|
context: callback];
|
|
|
|
|
return;
|
|
|
|
|
case _C_CHR:
|
|
|
|
|
case _C_UCHR:
|
|
|
|
|
(*appendImp)(self, appendSel, data, sizeof(unsigned char));
|
|
|
|
|
return;
|
|
|
|
|
case _C_SHT:
|
|
|
|
|
case _C_USHT:
|
|
|
|
|
{
|
|
|
|
|
unsigned short ns = NSSwapHostShortToBig(*(unsigned short*)data);
|
|
|
|
|
(*appendImp)(self, appendSel, &ns, sizeof(unsigned short));
|
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_INT:
|
|
|
|
|
case _C_UINT:
|
|
|
|
|
{
|
|
|
|
|
unsigned ni = NSSwapHostIntToBig(*(unsigned int*)data);
|
|
|
|
|
(*appendImp)(self, appendSel, &ni, sizeof(unsigned));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case _C_LNG:
|
|
|
|
|
case _C_ULNG:
|
|
|
|
|
{
|
|
|
|
|
unsigned long nl = NSSwapHostLongToBig(*(unsigned long*)data);
|
|
|
|
|
(*appendImp)(self, appendSel, &nl, sizeof(unsigned long));
|
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_LNG_LNG:
|
|
|
|
|
case _C_ULNG_LNG:
|
|
|
|
|
{
|
|
|
|
|
unsigned long long nl;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
1999-02-01 12:05:15 +00:00
|
|
|
|
nl = NSSwapHostLongLongToBig(*(unsigned long long*)data);
|
|
|
|
|
(*appendImp)(self, appendSel, &nl, sizeof(unsigned long long));
|
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_FLT:
|
|
|
|
|
{
|
|
|
|
|
NSSwappedFloat nf = NSSwapHostFloatToBig(*(float*)data);
|
|
|
|
|
(*appendImp)(self, appendSel, &nf, sizeof(NSSwappedFloat));
|
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_DBL:
|
|
|
|
|
{
|
|
|
|
|
NSSwappedDouble nd = NSSwapHostDoubleToBig(*(double*)data);
|
|
|
|
|
(*appendImp)(self, appendSel, &nd, sizeof(NSSwappedDouble));
|
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_CLASS:
|
|
|
|
|
{
|
2010-02-22 10:13:20 +00:00
|
|
|
|
const char *name = *(Class*)data?class_getName(*(Class*)data):"";
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t ln = (uint16_t)strlen(name);
|
|
|
|
|
uint32_t minimum = length + ln + sizeof(uint16_t);
|
|
|
|
|
uint16_t ni;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
|
|
|
|
|
if (minimum > capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: minimum];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI16ToBig(ln);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
memcpy(bytes+length, &ni, sizeof(ni));
|
|
|
|
|
length += sizeof(ni);
|
|
|
|
|
if (ln)
|
|
|
|
|
{
|
|
|
|
|
memcpy(bytes+length, name, ln);
|
|
|
|
|
length += ln;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
case _C_SEL:
|
|
|
|
|
{
|
2010-02-22 10:13:20 +00:00
|
|
|
|
const char *name = *(SEL*)data?sel_getName(*(SEL*)data):"";
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t ln = (name == 0) ? 0 : (uint16_t)strlen(name);
|
2002-02-21 13:31:13 +00:00
|
|
|
|
const char *types = *(SEL*)data?GSTypesFromSelector(*(SEL*)data):"";
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t lt = (types == 0) ? 0 : (uint16_t)strlen(types);
|
|
|
|
|
uint32_t minimum = length + ln + lt + 2*sizeof(uint16_t);
|
|
|
|
|
uint16_t ni;
|
1999-02-01 12:05:15 +00:00
|
|
|
|
|
|
|
|
|
if (minimum > capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: minimum];
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI16ToBig(ln);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
memcpy(bytes+length, &ni, sizeof(ni));
|
|
|
|
|
length += sizeof(ni);
|
1999-02-08 10:46:32 +00:00
|
|
|
|
ni = GSSwapHostI16ToBig(lt);
|
1999-02-01 12:05:15 +00:00
|
|
|
|
memcpy(bytes+length, &ni, sizeof(ni));
|
|
|
|
|
length += sizeof(ni);
|
|
|
|
|
if (ln)
|
|
|
|
|
{
|
|
|
|
|
memcpy(bytes+length, name, ln);
|
|
|
|
|
length += ln;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
if (lt)
|
|
|
|
|
{
|
|
|
|
|
memcpy(bytes+length, types, lt);
|
|
|
|
|
length += lt;
|
1998-10-22 20:20:31 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
return;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-02-01 12:05:15 +00:00
|
|
|
|
default:
|
2002-10-07 13:46:22 +00:00
|
|
|
|
[NSException raise: NSMallocException
|
1999-02-01 12:05:15 +00:00
|
|
|
|
format: @"Unknown type to serialize - '%s'", type];
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
1998-10-23 15:48:21 +00:00
|
|
|
|
- (void) serializeTypeTag: (unsigned char)tag
|
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (length == capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: length + 1];
|
1998-10-23 15:48:21 +00:00
|
|
|
|
}
|
1999-01-27 12:49:49 +00:00
|
|
|
|
((unsigned char*)bytes)[length++] = tag;
|
1998-10-23 15:48:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-01-27 12:49:49 +00:00
|
|
|
|
- (void) serializeTypeTag: (unsigned char)tag
|
2001-12-17 14:31:42 +00:00
|
|
|
|
andCrossRef: (unsigned int)xref
|
1998-10-23 15:48:21 +00:00
|
|
|
|
{
|
1999-01-27 12:49:49 +00:00
|
|
|
|
if (xref <= 0xff)
|
|
|
|
|
{
|
|
|
|
|
tag = (tag & ~_GSC_SIZE) | _GSC_X_1;
|
|
|
|
|
if (length + 2 >= capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: length + 2];
|
|
|
|
|
}
|
2006-01-11 08:37:16 +00:00
|
|
|
|
*(uint8_t*)(bytes + length++) = tag;
|
|
|
|
|
*(uint8_t*)(bytes + length++) = xref;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
else if (xref <= 0xffff)
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint16_t x = (uint16_t)xref;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
tag = (tag & ~_GSC_SIZE) | _GSC_X_2;
|
|
|
|
|
if (length + 3 >= capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: length + 3];
|
|
|
|
|
}
|
2006-01-11 08:37:16 +00:00
|
|
|
|
*(uint8_t*)(bytes + length++) = tag;
|
2000-05-23 16:26:40 +00:00
|
|
|
|
#if NEED_WORD_ALIGNMENT
|
2006-01-11 08:37:16 +00:00
|
|
|
|
if ((length % __alignof__(uint16_t)) != 0)
|
2000-05-03 03:14:14 +00:00
|
|
|
|
{
|
|
|
|
|
x = GSSwapHostI16ToBig(x);
|
|
|
|
|
memcpy((bytes + length), &x, 2);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
2006-01-11 08:37:16 +00:00
|
|
|
|
*(uint16_t*)(bytes + length) = GSSwapHostI16ToBig(x);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
length += 2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2006-01-11 08:37:16 +00:00
|
|
|
|
uint32_t x = (uint32_t)xref;
|
1999-01-27 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
tag = (tag & ~_GSC_SIZE) | _GSC_X_4;
|
|
|
|
|
if (length + 5 >= capacity)
|
|
|
|
|
{
|
|
|
|
|
[self _grow: length + 5];
|
|
|
|
|
}
|
2006-01-11 08:37:16 +00:00
|
|
|
|
*(uint8_t*)(bytes + length++) = tag;
|
2000-05-23 16:26:40 +00:00
|
|
|
|
#if NEED_WORD_ALIGNMENT
|
2006-01-11 08:37:16 +00:00
|
|
|
|
if ((length % __alignof__(uint32_t)) != 0)
|
2000-05-03 03:14:14 +00:00
|
|
|
|
{
|
|
|
|
|
x = GSSwapHostI32ToBig(x);
|
|
|
|
|
memcpy((bytes + length), &x, 4);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
2006-01-11 08:37:16 +00:00
|
|
|
|
*(uint32_t*)(bytes + length) = GSSwapHostI32ToBig(x);
|
1999-01-27 12:49:49 +00:00
|
|
|
|
length += 4;
|
1998-10-23 15:48:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) setCapacity: (NSUInteger)size
|
1998-10-21 11:56:58 +00:00
|
|
|
|
{
|
1999-09-29 20:15:17 +00:00
|
|
|
|
if (size != capacity)
|
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
void *tmp;
|
|
|
|
|
|
|
|
|
|
#if GS_WITH_GC
|
|
|
|
|
tmp = NSAllocateCollectable(size, 0);
|
|
|
|
|
if (tmp == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
|
format: @"Unable to set data capacity to '%d'", size];
|
|
|
|
|
}
|
1999-09-29 20:15:17 +00:00
|
|
|
|
if (bytes)
|
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
memcpy(tmp, bytes, capacity < size ? capacity : size);
|
2009-04-15 08:03:19 +00:00
|
|
|
|
if (owned == YES)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), bytes);
|
|
|
|
|
owned = NO;
|
|
|
|
|
}
|
2009-08-10 14:13:09 +00:00
|
|
|
|
}
|
2009-04-15 08:03:19 +00:00
|
|
|
|
#else
|
2009-08-10 14:13:09 +00:00
|
|
|
|
tmp = NSZoneMalloc(zone, size);
|
|
|
|
|
if (tmp == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
|
format: @"Unable to set data capacity to '%d'", size];
|
|
|
|
|
}
|
|
|
|
|
if (bytes)
|
|
|
|
|
{
|
|
|
|
|
memcpy(tmp, bytes, capacity < size ? capacity : size);
|
2002-08-27 12:26:17 +00:00
|
|
|
|
if (zone == 0)
|
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
zone = NSDefaultMallocZone();
|
2002-08-27 12:26:17 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-03-10 09:35:14 +00:00
|
|
|
|
NSZoneFree(zone, bytes);
|
2002-08-27 12:26:17 +00:00
|
|
|
|
}
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
2009-08-10 14:13:09 +00:00
|
|
|
|
else if (zone == 0)
|
|
|
|
|
{
|
|
|
|
|
zone = NSDefaultMallocZone();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
1999-09-29 20:15:17 +00:00
|
|
|
|
bytes = tmp;
|
|
|
|
|
capacity = size;
|
|
|
|
|
growth = capacity/2;
|
|
|
|
|
if (growth == 0)
|
|
|
|
|
{
|
|
|
|
|
growth = 1;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-09-29 20:15:17 +00:00
|
|
|
|
if (size < length)
|
|
|
|
|
{
|
|
|
|
|
length = size;
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
1999-09-29 20:15:17 +00:00
|
|
|
|
return self;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
- (void) setData: (NSData*)data
|
|
|
|
|
{
|
|
|
|
|
unsigned l = [data length];
|
|
|
|
|
|
|
|
|
|
[self setCapacity: l];
|
|
|
|
|
length = l;
|
|
|
|
|
memcpy(bytes, [data bytes], length);
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) setLength: (NSUInteger)size
|
1998-02-05 22:06:20 +00:00
|
|
|
|
{
|
2001-04-10 03:27:01 +00:00
|
|
|
|
if (size > capacity)
|
|
|
|
|
{
|
|
|
|
|
[self setCapacity: size];
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
2001-04-10 03:27:01 +00:00
|
|
|
|
if (size > length)
|
|
|
|
|
{
|
|
|
|
|
memset(bytes + length, '\0', size - length);
|
1998-10-21 11:56:58 +00:00
|
|
|
|
}
|
2001-04-10 03:27:01 +00:00
|
|
|
|
length = size;
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@end
|
|
|
|
|
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#if GS_WITH_GC
|
2009-04-15 08:03:19 +00:00
|
|
|
|
@implementation NSMutableDataFinalized
|
|
|
|
|
- (void) finalize
|
|
|
|
|
{
|
|
|
|
|
if (owned == YES)
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), bytes);
|
|
|
|
|
[super finalize];
|
|
|
|
|
}
|
|
|
|
|
@end
|
2009-04-15 08:25:52 +00:00
|
|
|
|
#endif
|
2009-04-15 08:03:19 +00:00
|
|
|
|
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SHMCTL
|
1997-09-29 14:39:53 +00:00
|
|
|
|
@implementation NSMutableDataShared
|
2000-04-14 10:38:22 +00:00
|
|
|
|
+ (id) allocWithZone: (NSZone*)z
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
return (NSData*)NSAllocateObject([NSMutableDataShared class], 0, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
2009-04-15 08:03:19 +00:00
|
|
|
|
{
|
|
|
|
|
[self finalize];
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) finalize
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
2001-06-01 15:51:34 +00:00
|
|
|
|
if (bytes != 0)
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
1997-10-28 14:34:49 +00:00
|
|
|
|
struct shmid_ds buf;
|
|
|
|
|
|
|
|
|
|
if (shmctl(shmid, IPC_STAT, &buf) < 0)
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSMutableDataShared -dealloc] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"control failed - %@", [NSError _last]);
|
2003-03-23 07:06:27 +00:00
|
|
|
|
}
|
1997-10-28 14:34:49 +00:00
|
|
|
|
else if (buf.shm_nattch == 1)
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSMutableDataShared -dealloc] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"delete failed - %@", [NSError _last]);
|
2003-03-23 07:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1997-10-28 14:34:49 +00:00
|
|
|
|
if (shmdt(bytes) < 0)
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSMutableDataShared -dealloc] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"detach failed - %@", [NSError _last]);
|
2003-03-23 07:06:27 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = 0;
|
|
|
|
|
length = 0;
|
|
|
|
|
capacity = 0;
|
|
|
|
|
shmid = -1;
|
|
|
|
|
}
|
2009-04-15 08:03:19 +00:00
|
|
|
|
[super finalize];
|
1997-09-29 14:39:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithCapacity: (NSUInteger)bufferSize
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
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
|
|
|
|
{
|
2003-03-23 07:06:27 +00:00
|
|
|
|
NSLog(@"[NSMutableDataShared -initWithCapacity:] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"get failed for %u - %@", bufferSize, [NSError _last]);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
1999-05-06 14:42:26 +00:00
|
|
|
|
self = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
1998-10-15 05:03:16 +00:00
|
|
|
|
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);
|
|
|
|
|
if (bytes == (void*)-1)
|
|
|
|
|
{
|
2003-03-23 07:06:27 +00:00
|
|
|
|
NSLog(@"[NSMutableDataShared -initWithCapacity:] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"attach failed for %u - %@", bufferSize, [NSError _last]);
|
1998-10-15 05:03:16 +00:00
|
|
|
|
bytes = 0;
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
1999-05-06 14:42:26 +00:00
|
|
|
|
self = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()];
|
1998-10-15 05:03:16 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithShmID: (int)anId length: (NSUInteger)bufferSize
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
{
|
2003-03-23 07:06:27 +00:00
|
|
|
|
NSLog(@"[NSMutableDataShared -initWithShmID:length:] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"control failed - %@", [NSError _last]);
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self); /* Unable to access memory. */
|
1998-10-15 05:03:16 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
if (buf.shm_segsz < bufferSize)
|
|
|
|
|
{
|
2003-03-23 07:06:27 +00:00
|
|
|
|
NSLog(@"[NSMutableDataShared -initWithShmID:length:] shared memory "
|
|
|
|
|
@"segment too small");
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self); /* Memory segment too small. */
|
1998-10-15 05:03:16 +00:00
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
bytes = shmat(shmid, 0, 0);
|
|
|
|
|
if (bytes == (void*)-1)
|
|
|
|
|
{
|
2003-03-23 07:06:27 +00:00
|
|
|
|
NSLog(@"[NSMutableDataShared -initWithShmID:length:] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"attach failed - %@", [NSError _last]);
|
1998-10-15 05:03:16 +00:00
|
|
|
|
bytes = 0;
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self); /* Unable to attach to memory. */
|
1998-10-15 05:03:16 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) setCapacity: (NSUInteger)size
|
1997-09-29 14:39:53 +00:00
|
|
|
|
{
|
|
|
|
|
if (size != capacity)
|
|
|
|
|
{
|
1999-06-24 19:30:29 +00:00
|
|
|
|
void *tmp;
|
|
|
|
|
int newid;
|
1997-09-29 14:39:53 +00:00
|
|
|
|
|
|
|
|
|
newid = shmget(IPC_PRIVATE, size, IPC_CREAT|VM_ACCESS);
|
|
|
|
|
if (newid == -1) /* Created memory? */
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
2006-10-09 14:00:01 +00:00
|
|
|
|
format: @"Unable to create shared memory segment (size:%u) - %@.",
|
2006-10-20 10:56:27 +00:00
|
|
|
|
size, [NSError _last]];
|
2003-03-23 07:06:27 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
tmp = shmat(newid, 0, 0);
|
2006-01-10 10:29:11 +00:00
|
|
|
|
if ((intptr_t)tmp == -1) /* Attached memory? */
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
|
format: @"Unable to attach to shared memory segment."];
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
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)
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"control failed - %@", [NSError _last]);
|
2003-03-23 07:06:27 +00:00
|
|
|
|
}
|
1997-10-28 14:34:49 +00:00
|
|
|
|
else if (buf.shm_nattch == 1)
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"delete failed - %@", [NSError _last]);
|
2003-03-23 07:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1997-10-28 14:34:49 +00:00
|
|
|
|
if (shmdt(bytes) < 0) /* Detach memory. */
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory "
|
2006-10-20 10:56:27 +00:00
|
|
|
|
@"detach failed - %@", [NSError _last]);
|
2003-03-23 07:06:27 +00:00
|
|
|
|
}
|
1997-10-28 14:34:49 +00:00
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
bytes = tmp;
|
|
|
|
|
shmid = newid;
|
|
|
|
|
capacity = size;
|
|
|
|
|
}
|
|
|
|
|
if (size < length)
|
2003-03-23 07:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
length = size;
|
|
|
|
|
}
|
1997-09-29 14:39:53 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (int) shmID
|
|
|
|
|
{
|
|
|
|
|
return shmid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
#endif /* HAVE_SHMCTL */
|
|
|
|
|
|