mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
NSString mutability fixes.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@19927 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
150d8f0a97
commit
06c824b4f9
3 changed files with 75 additions and 56 deletions
|
@ -3,6 +3,10 @@
|
|||
* Headers/Foundation/NSURLHandle.h:
|
||||
* Source/GSHTTPURLHandle.m:
|
||||
* Source/NSURLHandle.m: Fix property key names
|
||||
* Source/NSString.m: copy and autorelease potentially mutable strings
|
||||
before returning them.
|
||||
* Headers/Foundation/NSString.h: Document policy and warnings about
|
||||
lifetime and mutablity of strings returned from methods.
|
||||
|
||||
2004-08-25 Adrian Robert <arobert@cogsci.ucsd.edu>
|
||||
|
||||
|
|
|
@ -127,6 +127,50 @@ enum {
|
|||
NSOpenStepUnicodeReservedBase = 0xF400
|
||||
};
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* <code>NSString</code> objects represent an immutable string of Unicode 3.0
|
||||
* characters. These may be accessed individually as type
|
||||
* <code>unichar</code>, an unsigned short.<br/>
|
||||
* The [NSMutableString] subclass represents a modifiable string. Both are
|
||||
* implemented as part of a class cluster and the instances you receive may
|
||||
* actually be of unspecified concrete subclasses.
|
||||
* </p>
|
||||
* <p>
|
||||
* A constant <code>NSString</code> can be created using the following syntax:
|
||||
* <code>@"..."</code>, where the contents of the quotes are the
|
||||
* string, using only ASCII characters.
|
||||
* </p>
|
||||
* <p>
|
||||
* A variable string can be created using a C printf-like <em>format</em>,
|
||||
* as in <code>[NSString stringWithFormat: @"Total is %f", t]</code>.
|
||||
* </p>
|
||||
* <p>
|
||||
* To create a concrete subclass of <code>NSString</code>, you must have your
|
||||
* class inherit from <code>NSString</code> and override at least the two
|
||||
* primitive methods - -length and -characterAtIndex:
|
||||
* </p>
|
||||
* <p>
|
||||
* In general the rule is that your subclass must override any
|
||||
* initialiser that you want to use with it. The GNUstep
|
||||
* implementation relaxes that to say that, you may override
|
||||
* only the <em>designated initialiser</em> and the other
|
||||
* initialisation methods should work.
|
||||
* </p>
|
||||
* <p>
|
||||
* Where an NSString instance method returns an NSString object,
|
||||
* the class of the actual object returned may be any subclass
|
||||
* of NSString. The actual value returned may be a new
|
||||
* autoreleased object, an autoreleased copy of the receiver,
|
||||
* or the receiver itsself. While the abstract base class
|
||||
* implementations of methods (other than initialisers) will
|
||||
* avoid returning mutable strings by returning an autoreleased
|
||||
* copy of a mutable receiver, concrete subclasses may behave
|
||||
* differently, so code should not rely upon the mutability of
|
||||
* returned strings nor upon their lifetime being create than
|
||||
* that of the receiver which returned them.
|
||||
* </p>
|
||||
*/
|
||||
@interface NSString :NSObject <NSCoding, NSCopying, NSMutableCopying>
|
||||
|
||||
// Creating Temporary Strings
|
||||
|
|
|
@ -110,6 +110,7 @@ static NSLock *placeholderLock;
|
|||
|
||||
static SEL cMemberSel = 0;
|
||||
|
||||
#define IMMUTABLE(S) AUTORELEASE([(S) copyWithZone: NSDefaultMallocZone()])
|
||||
|
||||
#define IS_BIT_SET(a,i) ((((a) & (1<<(i)))) > 0)
|
||||
|
||||
|
@ -200,37 +201,6 @@ surrogatePairValue(unichar high, unichar low)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* <code>NSString</code> objects represent an immutable string of Unicode 3.0
|
||||
* characters. These may be accessed individually as type
|
||||
* <code>unichar</code>, an unsigned short.<br/>
|
||||
* The [NSMutableString] subclass represents a modifiable string. Both are
|
||||
* implemented as part of a class cluster and the instances you receive may
|
||||
* actually be of unspecified concrete subclasses.
|
||||
* </p>
|
||||
* <p>
|
||||
* A constant <code>NSString</code> can be created using the following syntax:
|
||||
* <code>@"..."</code>, where the contents of the quotes are the
|
||||
* string, using only ASCII characters.
|
||||
* </p>
|
||||
* <p>
|
||||
* A variable string can be created using a C printf-like <em>format</em>,
|
||||
* as in <code>[NSString stringWithFormat: @"Total is %f", t]</code>.
|
||||
* </p>
|
||||
* <p>
|
||||
* To create a concrete subclass of <code>NSString</code>, you must have your
|
||||
* class inherit from <code>NSString</code> and override at least the two
|
||||
* primitive methods - -length and -characterAtIndex:
|
||||
* </p>
|
||||
* <p>
|
||||
* In general the rule is that your subclass must override any
|
||||
* initialiser that you want to use with it. The GNUstep
|
||||
* implementation relaxes that to say that, you may override
|
||||
* only the <em>designated initialiser</em> and the other
|
||||
* initialisation methods should work.
|
||||
* </p>
|
||||
*/
|
||||
@implementation NSString
|
||||
// NSString itself is an abstract class which provides factory
|
||||
// methods to generate objects of unspecified subclasses.
|
||||
|
@ -2237,9 +2207,9 @@ handle_printf_atsign (FILE *stream,
|
|||
unsigned oIndex = 0;
|
||||
|
||||
if (!sLength)
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
if (!oLength)
|
||||
return aString;
|
||||
return IMMUTABLE(aString);
|
||||
|
||||
scImp = (unichar (*)(NSString*,SEL,unsigned))
|
||||
[self methodForSelector: caiSel];
|
||||
|
@ -2496,7 +2466,7 @@ handle_printf_atsign (FILE *stream,
|
|||
unsigned len = [self length];
|
||||
|
||||
if (len == 0)
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
if (whitespaceBitmapRep == NULL)
|
||||
setupWhitespace();
|
||||
|
||||
|
@ -2551,7 +2521,7 @@ handle_printf_atsign (FILE *stream,
|
|||
|
||||
if (len == 0)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
if (uc == nil)
|
||||
{
|
||||
|
@ -2562,7 +2532,7 @@ handle_printf_atsign (FILE *stream,
|
|||
range: ((NSRange){0, len})];
|
||||
if (start.length == 0)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
s = NSZoneMalloc(GSObjCZone(self), sizeof(unichar)*len);
|
||||
[self getCharacters: s range: ((NSRange){0, len})];
|
||||
|
@ -2588,7 +2558,7 @@ handle_printf_atsign (FILE *stream,
|
|||
|
||||
if (len == 0)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
if (lc == nil)
|
||||
{
|
||||
|
@ -2599,7 +2569,7 @@ handle_printf_atsign (FILE *stream,
|
|||
range: ((NSRange){0, len})];
|
||||
if (start.length == 0)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
s = NSZoneMalloc(GSObjCZone(self), sizeof(unichar)*len);
|
||||
[self getCharacters: s range: ((NSRange){0, len})];
|
||||
|
@ -3519,7 +3489,8 @@ handle_printf_atsign (FILE *stream,
|
|||
* Returns a string created by expanding the initial tilde ('~') and any
|
||||
* following username to be the home directory of the current user or the
|
||||
* named user.<br />
|
||||
* Returns the receiver if it was not possible to expand it.
|
||||
* Returns the receiver or an immutable copy if it was not possible to
|
||||
* expand it.
|
||||
*/
|
||||
- (NSString*) stringByExpandingTildeInPath
|
||||
{
|
||||
|
@ -3529,11 +3500,11 @@ handle_printf_atsign (FILE *stream,
|
|||
|
||||
if ((length = [self length]) == 0)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
if ([self characterAtIndex: 0] != 0x007E)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3542,7 +3513,7 @@ handle_printf_atsign (FILE *stream,
|
|||
*/
|
||||
if (length > 1 && [self characterAtIndex: 1] == 0x0040)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
|
||||
first_slash_range = [self rangeOfCharacterFromSet: pathSeps()
|
||||
|
@ -3580,14 +3551,14 @@ handle_printf_atsign (FILE *stream,
|
|||
}
|
||||
else
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string where a prefix of the current user's home directory is
|
||||
* abbreviated by '~', or returns the receiver if it was not found to have
|
||||
* the home directory as a prefix.
|
||||
* abbreviated by '~', or returns the receiver (or an immutable copy) if
|
||||
* it was not found to have the home directory as a prefix.
|
||||
*/
|
||||
- (NSString*) stringByAbbreviatingWithTildeInPath
|
||||
{
|
||||
|
@ -3595,7 +3566,7 @@ handle_printf_atsign (FILE *stream,
|
|||
|
||||
if (![self hasPrefix: homedir])
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
if ([self length] == [homedir length])
|
||||
{
|
||||
|
@ -3632,7 +3603,7 @@ handle_printf_atsign (FILE *stream,
|
|||
}
|
||||
if (newLength == length)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
else if (newLength < length)
|
||||
{
|
||||
|
@ -3792,7 +3763,7 @@ handle_printf_atsign (FILE *stream,
|
|||
- (NSString*) stringByResolvingSymlinksInPath
|
||||
{
|
||||
#if defined(__MINGW__)
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
#else
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 1024
|
||||
|
@ -3801,7 +3772,7 @@ handle_printf_atsign (FILE *stream,
|
|||
#ifdef HAVE_REALPATH
|
||||
|
||||
if (realpath([self fileSystemRepresentation], new_buf) == 0)
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
#else
|
||||
char extra[MAX_PATH];
|
||||
char *dest;
|
||||
|
@ -3814,7 +3785,7 @@ handle_printf_atsign (FILE *stream,
|
|||
if (name[0] != '/')
|
||||
{
|
||||
if (!getcwd(new_buf, MAX_PATH))
|
||||
return self; /* Couldn't get directory. */
|
||||
return IMMUTABLE(self); /* Couldn't get directory. */
|
||||
dest = strchr(new_buf, '\0');
|
||||
}
|
||||
else
|
||||
|
@ -3867,30 +3838,30 @@ handle_printf_atsign (FILE *stream,
|
|||
*dest++ = '/';
|
||||
|
||||
if (&dest[len] >= &new_buf[MAX_PATH])
|
||||
return self; /* Resolved name would be too long. */
|
||||
return IMMUTABLE(self); /* Resolved name too long. */
|
||||
|
||||
memcpy(dest, start, len);
|
||||
dest += len;
|
||||
*dest = '\0';
|
||||
|
||||
if (lstat(new_buf, &st) < 0)
|
||||
return self; /* Unable to stat file. */
|
||||
return IMMUTABLE(self); /* Unable to stat file. */
|
||||
|
||||
if (S_ISLNK(st.st_mode))
|
||||
{
|
||||
char buf[MAX_PATH];
|
||||
|
||||
if (++num_links > MAXSYMLINKS)
|
||||
return self; /* Too many symbolic links. */
|
||||
return IMMUTABLE(self); /* Too many symbolic links. */
|
||||
|
||||
n = readlink(new_buf, buf, MAX_PATH);
|
||||
if (n < 0)
|
||||
return self; /* Couldn't resolve links. */
|
||||
return IMMUTABLE(self); /* Couldn't resolve links. */
|
||||
|
||||
buf[n] = '\0';
|
||||
|
||||
if ((n + strlen(end)) >= MAX_PATH)
|
||||
return self; /* Path would be too long. */
|
||||
return IMMUTABLE(self); /* Path would be too long. */
|
||||
|
||||
/*
|
||||
* Concatenate the resolved name with the string still to
|
||||
|
@ -4118,7 +4089,7 @@ handle_printf_atsign (FILE *stream,
|
|||
}
|
||||
if (start == 0 && end == length)
|
||||
{
|
||||
return self;
|
||||
return IMMUTABLE(self);
|
||||
}
|
||||
if (start == end)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue